These changes:
* Rework the pinctrl API as we discussed at Linaro Connect.
* Allow specifying pin config settings in the mapping table in addition
to mux options, as we agreed upon at Linaro Connect.
* Various cleanups and refactorings aimed at supporting the changes above.
TODO in this patch set:
* Test build of non-Tegra platforms.
* Test build with pinmux/pinconf disabled.
... but I figure it was a good idea to send out for comments ASAP.
TODO in future patch sets:
* Implement device tree support in pinctrl core and a pinctrl driver.
* Remove pin config APIs from pinctrl now that the mapping table supports
pin config?
I've tested this all on a couple Tegra boards, including hacking in a single
pin config and dummy state mapping table entry. I've got patches for Tegra
boards that use the explicit pin config APIs, and need to convert them to
using the pin config mapping table entries for more complete testing.
(In the diffstat below, I /think/ the first 19 patches are a net negative in
line-count, and only the last patch, which implements a new feature, adds a
significant number of lines)
Stephen Warren (20):
pinctrl: pinctrl_register_mappings() shouldn't be __init
pinctrl: use list_add_tail instead of list_add
pinctrl: Store mapping table as a list of chunks
pinctrl: Record a pin owner, not mux function, when requesting pins
pinctrl: Re-order pinmux.[ch] to match each-other
pinctrl: Re-order pinconf.[ch] to match each-other
pinctrl: core.c/h cleanups
pinctrl: Assume map table entries can't have a NULL name field
pinctrl: Disallow map table entries with NULL dev_name field
pinctrl: Assume map table entries can't have a NULL ctrl_dev_name
field
pinctrl: Downgrade pinctrl_get warning when no maps are found
pinctrl: Use dev_*() instead of pr_*(), add some msgs, minor cleanups
pinctrl: Error if mapping table's control dev can't be found
pinctrl: Allocate sizeof(*p) instead of sizeof(struct foo)
pinctrl: Fix and simplify locking
pinctrl: Refactor struct pinctrl handling in core.c vs pinmux.c
pinctrl: Add usecount to pins for muxing
pinctrl: Fix pinconf_groups_show() to emit newline
pinctrl: API changes to support multiple states per device
pinctrl: Enhance mapping table to support pin config operations
Documentation/pinctrl.txt | 244 +++++++----
arch/arm/mach-u300/core.c | 28 +-
drivers/pinctrl/core.c | 936 +++++++++++++++++++++----------------
drivers/pinctrl/core.h | 100 +++--
drivers/pinctrl/pinconf.c | 288 ++++++++++--
drivers/pinctrl/pinconf.h | 45 ++-
drivers/pinctrl/pinmux.c | 578 ++++++++---------------
drivers/pinctrl/pinmux.h | 61 ++--
drivers/tty/serial/sirfsoc_uart.c | 12 +-
include/linux/pinctrl/consumer.h | 55 ++-
include/linux/pinctrl/machine.h | 131 ++++--
include/linux/pinctrl/pinctrl.h | 1 -
12 files changed, 1438 insertions(+), 1041 deletions(-)
--
1.7.5.4
It may be common for pinctrl_register_mappings() to be used from __init
context, but there's no reason that additional mappings shouldn't be
added at a later point, e.g. if loading modules that add pin controllers
and their mapping tables.
Signed-off-by: Stephen Warren <[email protected]>
---
drivers/pinctrl/core.c | 15 +++++----------
1 files changed, 5 insertions(+), 10 deletions(-)
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index 8a91eb2..84a24a6 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -641,18 +641,13 @@ EXPORT_SYMBOL_GPL(pinctrl_disable);
/**
* pinctrl_register_mappings() - register a set of pin controller mappings
- * @maps: the pincontrol 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.
+ * @maps: the pincontrol mappings table to register. This should probably 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
- * tagged as __init and won't be callable after init has completed. The map
- * passed into this function will be owned by the pinmux core and cannot be
- * freed.
*/
-int __init pinctrl_register_mappings(struct pinctrl_map const *maps,
- unsigned num_maps)
+int pinctrl_register_mappings(struct pinctrl_map const *maps,
+ unsigned num_maps)
{
void *tmp_maps;
int i;
--
1.7.5.4
These are already disallowed. Clean up some code that doesn't assume this.
Signed-off-by: Stephen Warren <[email protected]>
---
drivers/pinctrl/core.c | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index 331ffb6..37dfac7 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -770,8 +770,7 @@ static int pinctrl_hog_maps(struct pinctrl_dev *pctldev)
mutex_lock(&pinctrl_maps_mutex);
for_each_maps(maps_node, i, map) {
- if (map->ctrl_dev_name &&
- !strcmp(map->ctrl_dev_name, devname) &&
+ if (!strcmp(map->ctrl_dev_name, devname) &&
!strcmp(map->dev_name, devname)) {
/* OK time to hog! */
ret = pinctrl_hog_map(pctldev, map);
--
1.7.5.4
There are many problems with the current pinctrl locking:
struct pinctrl_dev's pin_desc_tree_lock and pinctrl_hogs_lock aren't
useful; the data they protect is read-only except when registering or
unregistering a pinctrl_dev, and at those times, it doesn't make sense to
protect one part of the structure independently from the rest.
struct pinctrl_dev's gpio_ranges_lock isn't effective;
pinctrl_match_gpio_range() only holds this lock while searching for a gpio
range, but the found range is return and manipulated after releading the
lock. This could allow pinctrl_remove_gpio_range() for that range while it
is in use, and the caller may very well delete the range after removing it,
causing pinctrl code to touch the now-free range object.
Solving this requires the introduction of a higher-level lock, at least
a lock per pin controller, which both gpio range registration and
pinctrl_get()/put() will acquire.
There is missing locking on HW programming; pin controllers may pack the
configuration for different pins/groups/config options/... into one
register, and hence have to read-modify-write the register. This needs to
be protected, but currently isn't. Related, a future change will add a
"complete" op to the pin controller drivers, the idea being that each
state's programming will be programmed into the pinctrl driver followed
by the "complete" call, which may e.g. flush a register cache to HW. For
this to work, it must not be possible to interleave the pinctrl driver
calls for different devices.
As above, solving this requires the introduction of a higher-level lock,
at least a lock per pin controller, which will be held for the duration
of any pinctrl_enable()/disable() call.
However, each pinctrl mapping table entry may affect a different pin
controller if necessary. Hence, with a per-pin-controller lock, almost
any pinctrl API may need to acquire multiple locks, one per controller.
To avoid deadlock, these would need to be acquired in the same order in
all cases. This is extremely difficult to implement in the case of
pinctrl_get(), which doesn't know which pin controllers to lock until it
has parsed the entire mapping table, since it contains somewhat arbitrary
data.
The simplest solution here is to introduce a single lock that covers all
pin controllers at once. This will be acquired by all pinctrl APIs.
This then makes struct pinctrl's mutex irrelevant, since that single lock
will always be held whenever this mutex is currently held.
Signed-off-by: Stephen Warren <[email protected]>
---
drivers/pinctrl/core.c | 229 ++++++++++++++++++++++-----------------
drivers/pinctrl/core.h | 21 ++--
drivers/pinctrl/pinconf.c | 107 ++++++++++++++-----
drivers/pinctrl/pinmux.c | 22 ++---
include/linux/pinctrl/pinctrl.h | 1 -
5 files changed, 225 insertions(+), 155 deletions(-)
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index b8e6112..7cb64e6 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -18,11 +18,8 @@
#include <linux/init.h>
#include <linux/device.h>
#include <linux/slab.h>
-#include <linux/radix-tree.h>
#include <linux/err.h>
#include <linux/list.h>
-#include <linux/mutex.h>
-#include <linux/spinlock.h>
#include <linux/sysfs.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
@@ -56,16 +53,16 @@ struct pinctrl_hog {
struct pinctrl *p;
};
-/* Global list of pin control devices */
-static DEFINE_MUTEX(pinctrldev_list_mutex);
+/* Mutex taken by all entry points */
+DEFINE_MUTEX(pinctrl_mutex);
+
+/* Global list of pin control devices (struct pinctrl_dev) */
static LIST_HEAD(pinctrldev_list);
-/* List of pin controller handles */
-static DEFINE_MUTEX(pinctrl_list_mutex);
+/* List of pin controller handles (struct pinctrl) */
static LIST_HEAD(pinctrl_list);
-/* Global pinctrl maps */
-static DEFINE_MUTEX(pinctrl_maps_mutex);
+/* List of pinctrl maps (struct pinctrl_maps) */
static LIST_HEAD(pinctrl_maps);
#define for_each_maps(_maps_node_, _i_, _map_) \
@@ -102,7 +99,6 @@ struct pinctrl_dev *get_pinctrl_dev_from_devname(const char *devname)
if (!devname)
return NULL;
- mutex_lock(&pinctrldev_list_mutex);
list_for_each_entry(pctldev, &pinctrldev_list, node) {
if (!strcmp(dev_name(pctldev->dev), devname)) {
/* Matched on device name */
@@ -110,23 +106,10 @@ struct pinctrl_dev *get_pinctrl_dev_from_devname(const char *devname)
break;
}
}
- mutex_unlock(&pinctrldev_list_mutex);
return found ? pctldev : NULL;
}
-struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, unsigned int pin)
-{
- struct pin_desc *pindesc;
- unsigned long flags;
-
- spin_lock_irqsave(&pctldev->pin_desc_tree_lock, flags);
- pindesc = radix_tree_lookup(&pctldev->pin_desc_tree, pin);
- spin_unlock_irqrestore(&pctldev->pin_desc_tree_lock, flags);
-
- return pindesc;
-}
-
/**
* pin_get_from_name() - look up a pin number from a name
* @pctldev: the pin control device to lookup the pin on
@@ -167,11 +150,11 @@ bool pin_is_valid(struct pinctrl_dev *pctldev, int pin)
if (pin < 0)
return false;
+ mutex_lock(&pinctrl_mutex);
pindesc = pin_desc_get(pctldev, pin);
- if (pindesc == NULL)
- return false;
+ mutex_unlock(&pinctrl_mutex);
- return true;
+ return pindesc != NULL;
}
EXPORT_SYMBOL_GPL(pin_is_valid);
@@ -182,7 +165,6 @@ static void pinctrl_free_pindescs(struct pinctrl_dev *pctldev,
{
int i;
- spin_lock(&pctldev->pin_desc_tree_lock);
for (i = 0; i < num_pins; i++) {
struct pin_desc *pindesc;
@@ -196,7 +178,6 @@ static void pinctrl_free_pindescs(struct pinctrl_dev *pctldev,
}
kfree(pindesc);
}
- spin_unlock(&pctldev->pin_desc_tree_lock);
}
static int pinctrl_register_one_pin(struct pinctrl_dev *pctldev,
@@ -217,8 +198,6 @@ static int pinctrl_register_one_pin(struct pinctrl_dev *pctldev,
return -ENOMEM;
}
- spin_lock_init(&pindesc->lock);
-
/* Set owner */
pindesc->pctldev = pctldev;
@@ -232,9 +211,7 @@ static int pinctrl_register_one_pin(struct pinctrl_dev *pctldev,
pindesc->dynamic_name = true;
}
- spin_lock(&pctldev->pin_desc_tree_lock);
radix_tree_insert(&pctldev->pin_desc_tree, number, pindesc);
- spin_unlock(&pctldev->pin_desc_tree_lock);
pr_debug("registered pin %d (%s) on %s\n",
number, pindesc->name, pctldev->desc->name);
return 0;
@@ -271,16 +248,13 @@ pinctrl_match_gpio_range(struct pinctrl_dev *pctldev, unsigned gpio)
struct pinctrl_gpio_range *range = NULL;
/* Loop over the ranges */
- mutex_lock(&pctldev->gpio_ranges_lock);
list_for_each_entry(range, &pctldev->gpio_ranges, node) {
/* Check if we're in the valid range */
if (gpio >= range->base &&
gpio < range->base + range->npins) {
- mutex_unlock(&pctldev->gpio_ranges_lock);
return range;
}
}
- mutex_unlock(&pctldev->gpio_ranges_lock);
return NULL;
}
@@ -302,7 +276,6 @@ static int pinctrl_get_device_gpio_range(unsigned gpio,
struct pinctrl_dev *pctldev = NULL;
/* Loop over the pin controllers */
- mutex_lock(&pinctrldev_list_mutex);
list_for_each_entry(pctldev, &pinctrldev_list, node) {
struct pinctrl_gpio_range *range;
@@ -310,11 +283,9 @@ static int pinctrl_get_device_gpio_range(unsigned gpio,
if (range != NULL) {
*outdev = pctldev;
*outrange = range;
- mutex_unlock(&pinctrldev_list_mutex);
return 0;
}
}
- mutex_unlock(&pinctrldev_list_mutex);
return -EINVAL;
}
@@ -330,9 +301,9 @@ static int pinctrl_get_device_gpio_range(unsigned gpio,
void pinctrl_add_gpio_range(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range)
{
- mutex_lock(&pctldev->gpio_ranges_lock);
+ mutex_lock(&pinctrl_mutex);
list_add_tail(&range->node, &pctldev->gpio_ranges);
- mutex_unlock(&pctldev->gpio_ranges_lock);
+ mutex_unlock(&pinctrl_mutex);
}
EXPORT_SYMBOL_GPL(pinctrl_add_gpio_range);
@@ -344,9 +315,9 @@ EXPORT_SYMBOL_GPL(pinctrl_add_gpio_range);
void pinctrl_remove_gpio_range(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range)
{
- mutex_lock(&pctldev->gpio_ranges_lock);
+ mutex_lock(&pinctrl_mutex);
list_del(&range->node);
- mutex_unlock(&pctldev->gpio_ranges_lock);
+ mutex_unlock(&pinctrl_mutex);
}
EXPORT_SYMBOL_GPL(pinctrl_remove_gpio_range);
@@ -396,14 +367,21 @@ int pinctrl_request_gpio(unsigned gpio)
int ret;
int pin;
+ mutex_lock(&pinctrl_mutex);
+
ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range);
- if (ret)
+ if (ret) {
+ mutex_unlock(&pinctrl_mutex);
return -EINVAL;
+ }
/* Convert to the pin controllers number space */
pin = gpio - range->base + range->pin_base;
- return pinmux_request_gpio(pctldev, range, pin, gpio);
+ ret = pinmux_request_gpio(pctldev, range, pin, gpio);
+
+ mutex_unlock(&pinctrl_mutex);
+ return ret;
}
EXPORT_SYMBOL_GPL(pinctrl_request_gpio);
@@ -422,14 +400,20 @@ void pinctrl_free_gpio(unsigned gpio)
int ret;
int pin;
+ mutex_lock(&pinctrl_mutex);
+
ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range);
- if (ret)
+ if (ret) {
+ mutex_unlock(&pinctrl_mutex);
return;
+ }
/* Convert to the pin controllers number space */
pin = gpio - range->base + range->pin_base;
- return pinmux_free_gpio(pctldev, pin, range);
+ pinmux_free_gpio(pctldev, pin, range);
+
+ mutex_unlock(&pinctrl_mutex);
}
EXPORT_SYMBOL_GPL(pinctrl_free_gpio);
@@ -460,7 +444,11 @@ static int pinctrl_gpio_direction(unsigned gpio, bool input)
*/
int pinctrl_gpio_direction_input(unsigned gpio)
{
- return pinctrl_gpio_direction(gpio, true);
+ int ret;
+ mutex_lock(&pinctrl_mutex);
+ ret = pinctrl_gpio_direction(gpio, true);
+ mutex_unlock(&pinctrl_mutex);
+ return ret;
}
EXPORT_SYMBOL_GPL(pinctrl_gpio_direction_input);
@@ -474,7 +462,11 @@ EXPORT_SYMBOL_GPL(pinctrl_gpio_direction_input);
*/
int pinctrl_gpio_direction_output(unsigned gpio)
{
- return pinctrl_gpio_direction(gpio, false);
+ int ret;
+ mutex_lock(&pinctrl_mutex);
+ ret = pinctrl_gpio_direction(gpio, false);
+ mutex_unlock(&pinctrl_mutex);
+ return ret;
}
EXPORT_SYMBOL_GPL(pinctrl_gpio_direction_output);
@@ -507,7 +499,6 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev, const char *name)
dev_err(dev, "failed to alloc struct pinctrl\n");
return ERR_PTR(-ENOMEM);
}
- mutex_init(&p->mutex);
pinmux_init_pinctrl_handle(p);
/* Iterate over the pin control maps to locate the right ones */
@@ -559,9 +550,7 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev, const char *name)
dev_dbg(dev, "found %u maps for state %s\n", num_maps, name);
/* Add the pinmux to the global list */
- mutex_lock(&pinctrl_list_mutex);
list_add_tail(&p->node, &pinctrl_list);
- mutex_unlock(&pinctrl_list_mutex);
return p;
}
@@ -577,74 +566,91 @@ struct pinctrl *pinctrl_get(struct device *dev, const char *name)
{
struct pinctrl *p;
- mutex_lock(&pinctrl_maps_mutex);
+ mutex_lock(&pinctrl_mutex);
p = pinctrl_get_locked(dev, name);
- mutex_unlock(&pinctrl_maps_mutex);
+ mutex_unlock(&pinctrl_mutex);
return p;
}
EXPORT_SYMBOL_GPL(pinctrl_get);
-/**
- * pinctrl_put() - release a previously claimed pin control handle
- * @p: a pin control handle previously claimed by pinctrl_get()
- */
-void pinctrl_put(struct pinctrl *p)
+static void pinctrl_put_locked(struct pinctrl *p)
{
if (p == NULL)
return;
- mutex_lock(&p->mutex);
if (p->usecount)
pr_warn("releasing pin control handle with active users!\n");
/* Free the groups and all acquired pins */
pinmux_put(p);
- mutex_unlock(&p->mutex);
/* Remove from list */
- mutex_lock(&pinctrl_list_mutex);
list_del(&p->node);
- mutex_unlock(&pinctrl_list_mutex);
kfree(p);
}
-EXPORT_SYMBOL_GPL(pinctrl_put);
/**
- * pinctrl_enable() - enable a certain pin controller setting
- * @p: the pin control handle to enable, previously claimed by pinctrl_get()
+ * pinctrl_put() - release a previously claimed pin control handle
+ * @p: a pin control handle previously claimed by pinctrl_get()
*/
-int pinctrl_enable(struct pinctrl *p)
+void pinctrl_put(struct pinctrl *p)
+{
+ mutex_lock(&pinctrl_mutex);
+ pinctrl_put(p);
+ mutex_unlock(&pinctrl_mutex);
+}
+EXPORT_SYMBOL_GPL(pinctrl_put);
+
+static int pinctrl_enable_locked(struct pinctrl *p)
{
int ret = 0;
if (p == NULL)
return -EINVAL;
- mutex_lock(&p->mutex);
+
if (p->usecount++ == 0) {
ret = pinmux_enable(p);
if (ret)
p->usecount--;
}
- mutex_unlock(&p->mutex);
+
return ret;
}
-EXPORT_SYMBOL_GPL(pinctrl_enable);
/**
- * pinctrl_disable() - disable a certain pin control setting
- * @p: the pin control handle to disable, previously claimed by pinctrl_get()
+ * pinctrl_enable() - enable a certain pin controller setting
+ * @p: the pin control handle to enable, previously claimed by pinctrl_get()
*/
-void pinctrl_disable(struct pinctrl *p)
+int pinctrl_enable(struct pinctrl *p)
+{
+ int ret;
+ mutex_lock(&pinctrl_mutex);
+ ret = pinctrl_enable_locked(p);
+ mutex_unlock(&pinctrl_mutex);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pinctrl_enable);
+
+static void pinctrl_disable_locked(struct pinctrl *p)
{
if (p == NULL)
return;
- mutex_lock(&p->mutex);
if (--p->usecount == 0) {
pinmux_disable(p);
}
- mutex_unlock(&p->mutex);
+}
+
+/**
+ * pinctrl_disable() - disable a certain pin control setting
+ * @p: the pin control handle to disable, previously claimed by pinctrl_get()
+ */
+void pinctrl_disable(struct pinctrl *p)
+{
+ mutex_lock(&pinctrl_mutex);
+ pinctrl_disable_locked(p);
+ mutex_unlock(&pinctrl_mutex);
}
EXPORT_SYMBOL_GPL(pinctrl_disable);
@@ -704,9 +710,9 @@ int pinctrl_register_mappings(struct pinctrl_map const *maps,
return -ENOMEM;
}
- mutex_lock(&pinctrl_maps_mutex);
+ mutex_lock(&pinctrl_mutex);
list_add_tail(&maps_node->node, &pinctrl_maps);
- mutex_unlock(&pinctrl_maps_mutex);
+ mutex_unlock(&pinctrl_mutex);
return 0;
}
@@ -734,9 +740,9 @@ static int pinctrl_hog_map(struct pinctrl_dev *pctldev,
return PTR_ERR(p);
}
- ret = pinctrl_enable(p);
+ ret = pinctrl_enable_locked(p);
if (ret) {
- pinctrl_put(p);
+ pinctrl_put_locked(p);
kfree(hog);
dev_err(pctldev->dev,
"could not enable the %s pin control mapping for hogging\n",
@@ -749,9 +755,7 @@ static int pinctrl_hog_map(struct pinctrl_dev *pctldev,
dev_info(pctldev->dev, "hogged map %s, function %s\n", map->name,
map->function);
- mutex_lock(&pctldev->pinctrl_hogs_lock);
list_add_tail(&hog->node, &pctldev->pinctrl_hogs);
- mutex_unlock(&pctldev->pinctrl_hogs_lock);
return 0;
}
@@ -774,21 +778,16 @@ static int pinctrl_hog_maps(struct pinctrl_dev *pctldev)
struct pinctrl_map const *map;
INIT_LIST_HEAD(&pctldev->pinctrl_hogs);
- mutex_init(&pctldev->pinctrl_hogs_lock);
- mutex_lock(&pinctrl_maps_mutex);
for_each_maps(maps_node, i, map) {
if (!strcmp(map->ctrl_dev_name, devname) &&
!strcmp(map->dev_name, devname)) {
/* OK time to hog! */
ret = pinctrl_hog_map(pctldev, map);
- if (ret) {
- mutex_unlock(&pinctrl_maps_mutex);
+ if (ret)
return ret;
- }
}
}
- mutex_unlock(&pinctrl_maps_mutex);
return 0;
}
@@ -801,16 +800,14 @@ static void pinctrl_unhog_maps(struct pinctrl_dev *pctldev)
{
struct list_head *node, *tmp;
- mutex_lock(&pctldev->pinctrl_hogs_lock);
list_for_each_safe(node, tmp, &pctldev->pinctrl_hogs) {
struct pinctrl_hog *hog =
list_entry(node, struct pinctrl_hog, node);
- pinctrl_disable(hog->p);
- pinctrl_put(hog->p);
+ pinctrl_disable_locked(hog->p);
+ pinctrl_put_locked(hog->p);
list_del(node);
kfree(hog);
}
- mutex_unlock(&pctldev->pinctrl_hogs_lock);
}
#ifdef CONFIG_DEBUG_FS
@@ -823,6 +820,8 @@ static int pinctrl_pins_show(struct seq_file *s, void *what)
seq_printf(s, "registered pins: %d\n", pctldev->desc->npins);
+ mutex_lock(&pinctrl_mutex);
+
/* The pin number can be retrived from the pin controller descriptor */
for (i = 0; i < pctldev->desc->npins; i++) {
struct pin_desc *desc;
@@ -843,6 +842,8 @@ static int pinctrl_pins_show(struct seq_file *s, void *what)
seq_puts(s, "\n");
}
+ mutex_unlock(&pinctrl_mutex);
+
return 0;
}
@@ -856,6 +857,8 @@ static int pinctrl_groups_show(struct seq_file *s, void *what)
if (!ops)
return 0;
+ mutex_lock(&pinctrl_mutex);
+
seq_puts(s, "registered pin groups:\n");
while (ops->list_groups(pctldev, selector) >= 0) {
const unsigned *pins;
@@ -878,6 +881,7 @@ static int pinctrl_groups_show(struct seq_file *s, void *what)
selector++;
}
+ mutex_unlock(&pinctrl_mutex);
return 0;
}
@@ -889,8 +893,9 @@ static int pinctrl_gpioranges_show(struct seq_file *s, void *what)
seq_puts(s, "GPIO ranges handled:\n");
+ mutex_lock(&pinctrl_mutex);
+
/* Loop over the ranges */
- mutex_lock(&pctldev->gpio_ranges_lock);
list_for_each_entry(range, &pctldev->gpio_ranges, node) {
seq_printf(s, "%u: %s GPIOS [%u - %u] PINS [%u - %u]\n",
range->id, range->name,
@@ -898,7 +903,8 @@ static int pinctrl_gpioranges_show(struct seq_file *s, void *what)
range->pin_base,
(range->pin_base + range->npins - 1));
}
- mutex_unlock(&pctldev->gpio_ranges_lock);
+
+ mutex_unlock(&pinctrl_mutex);
return 0;
}
@@ -911,7 +917,8 @@ static int pinctrl_maps_show(struct seq_file *s, void *what)
seq_puts(s, "Pinctrl maps:\n");
- mutex_lock(&pinctrl_maps_mutex);
+ mutex_lock(&pinctrl_mutex);
+
for_each_maps(maps_node, i, map) {
seq_printf(s, "%s:\n", map->name);
seq_printf(s, " device: %s\n", map->dev_name);
@@ -920,7 +927,8 @@ static int pinctrl_maps_show(struct seq_file *s, void *what)
seq_printf(s, " group: %s\n", map->group ? map->group :
"(default)");
}
- mutex_unlock(&pinctrl_maps_mutex);
+
+ mutex_unlock(&pinctrl_mutex);
return 0;
}
@@ -932,9 +940,13 @@ static int pinmux_hogs_show(struct seq_file *s, void *what)
seq_puts(s, "Pin control map hogs held by device\n");
+ mutex_lock(&pinctrl_mutex);
+
list_for_each_entry(hog, &pctldev->pinctrl_hogs, node)
seq_printf(s, "%s\n", hog->map->name);
+ mutex_unlock(&pinctrl_mutex);
+
return 0;
}
@@ -943,7 +955,9 @@ static int pinctrl_devices_show(struct seq_file *s, void *what)
struct pinctrl_dev *pctldev;
seq_puts(s, "name [pinmux] [pinconf]\n");
- mutex_lock(&pinctrldev_list_mutex);
+
+ mutex_lock(&pinctrl_mutex);
+
list_for_each_entry(pctldev, &pinctrldev_list, node) {
seq_printf(s, "%s ", pctldev->desc->name);
if (pctldev->desc->pmxops)
@@ -956,7 +970,8 @@ static int pinctrl_devices_show(struct seq_file *s, void *what)
seq_puts(s, "no");
seq_puts(s, "\n");
}
- mutex_unlock(&pinctrldev_list_mutex);
+
+ mutex_unlock(&pinctrl_mutex);
return 0;
}
@@ -966,6 +981,9 @@ static int pinctrl_show(struct seq_file *s, void *what)
struct pinctrl *p;
seq_puts(s, "Requested pin control handlers their pinmux maps:\n");
+
+ mutex_lock(&pinctrl_mutex);
+
list_for_each_entry(p, &pinctrl_list, node) {
struct pinctrl_dev *pctldev = p->pctldev;
@@ -984,6 +1002,8 @@ static int pinctrl_show(struct seq_file *s, void *what)
p->dev ? dev_name(p->dev) : "(system)");
}
+ mutex_unlock(&pinctrl_mutex);
+
return 0;
}
@@ -1164,9 +1184,7 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
pctldev->desc = pctldesc;
pctldev->driver_data = driver_data;
INIT_RADIX_TREE(&pctldev->pin_desc_tree, GFP_KERNEL);
- spin_lock_init(&pctldev->pin_desc_tree_lock);
INIT_LIST_HEAD(&pctldev->gpio_ranges);
- mutex_init(&pctldev->gpio_ranges_lock);
pctldev->dev = dev;
/* If we're implementing pinmuxing, check the ops for sanity */
@@ -1201,10 +1219,14 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
}
pinctrl_init_device_debugfs(pctldev);
- mutex_lock(&pinctrldev_list_mutex);
+
+ mutex_lock(&pinctrl_mutex);
+
list_add_tail(&pctldev->node, &pinctrldev_list);
- mutex_unlock(&pinctrldev_list_mutex);
pinctrl_hog_maps(pctldev);
+
+ mutex_unlock(&pinctrl_mutex);
+
return pctldev;
out_err:
@@ -1225,15 +1247,18 @@ void pinctrl_unregister(struct pinctrl_dev *pctldev)
return;
pinctrl_remove_device_debugfs(pctldev);
+
+ mutex_lock(&pinctrl_mutex);
+
pinctrl_unhog_maps(pctldev);
/* TODO: check that no pinmuxes are still active? */
- mutex_lock(&pinctrldev_list_mutex);
list_del(&pctldev->node);
- mutex_unlock(&pinctrldev_list_mutex);
/* Destroy descriptor tree */
pinctrl_free_pindescs(pctldev, pctldev->desc->pins,
pctldev->desc->npins);
kfree(pctldev);
+
+ mutex_unlock(&pinctrl_mutex);
}
EXPORT_SYMBOL_GPL(pinctrl_unregister);
diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h
index 061c57d..4cdc38d 100644
--- a/drivers/pinctrl/core.h
+++ b/drivers/pinctrl/core.h
@@ -9,6 +9,8 @@
* License terms: GNU General Public License (GPL) version 2
*/
+#include <linux/mutex.h>
+#include <linux/radix-tree.h>
#include <linux/pinctrl/pinconf.h>
struct pinctrl_gpio_range;
@@ -20,15 +22,12 @@ struct pinctrl_gpio_range;
* controller
* @pin_desc_tree: each pin descriptor for this pin controller is stored in
* this radix tree
- * @pin_desc_tree_lock: lock for the descriptor tree
* @gpio_ranges: a list of GPIO ranges that is handled by this pin controller,
* ranges are added to this list at runtime
- * @gpio_ranges_lock: lock for the GPIO ranges list
* @dev: the device entry for this pin controller
* @owner: module providing the pin controller, used for refcounting
* @driver_data: driver data for drivers registering to the pin controller
* subsystem
- * @pinctrl_hogs_lock: lock for the pin control hog list
* @pinctrl_hogs: list of pin control maps hogged by this device
* @device_root: debugfs root for this device
*/
@@ -36,13 +35,10 @@ struct pinctrl_dev {
struct list_head node;
struct pinctrl_desc *desc;
struct radix_tree_root pin_desc_tree;
- spinlock_t pin_desc_tree_lock;
struct list_head gpio_ranges;
- struct mutex gpio_ranges_lock;
struct device *dev;
struct module *owner;
void *driver_data;
- struct mutex pinctrl_hogs_lock;
struct list_head pinctrl_hogs;
#ifdef CONFIG_DEBUG_FS
struct dentry *device_root;
@@ -56,7 +52,6 @@ struct pinctrl_dev {
* @usecount: the number of active users of this pin controller setting, used
* to keep track of nested use cases
* @pctldev: pin control device handling this pin control handle
- * @mutex: a lock for the pin control state holder
* @func_selector: the function selector for the pinmux device handling
* this pinmux
* @groups: the group selectors for the pinmux device and
@@ -69,7 +64,6 @@ struct pinctrl {
struct device *dev;
unsigned usecount;
struct pinctrl_dev *pctldev;
- struct mutex mutex;
#ifdef CONFIG_PINMUX
unsigned func_selector;
struct list_head groups;
@@ -82,7 +76,6 @@ struct pinctrl {
* @name: a name for the pin, e.g. the name of the pin/pad/finger on a
* datasheet or such
* @dynamic_name: if the name of this pin was dynamically allocated
- * @lock: a lock to protect the descriptor structure
* @mux_requested: whether the pin is already requested by pinmux or not
* @mux_function: a named muxing function for the pin that will be passed to
* subdrivers and shown in debugfs etc
@@ -91,7 +84,6 @@ struct pin_desc {
struct pinctrl_dev *pctldev;
const char *name;
bool dynamic_name;
- spinlock_t lock;
/* These fields only added when supporting pinmux drivers */
#ifdef CONFIG_PINMUX
const char *owner;
@@ -99,7 +91,14 @@ struct pin_desc {
};
struct pinctrl_dev *get_pinctrl_dev_from_devname(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_group_selector(struct pinctrl_dev *pctldev,
const char *pin_group);
+
+static inline struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev,
+ unsigned int pin)
+{
+ return radix_tree_lookup(&pctldev->pin_desc_tree, pin);
+}
+
+extern struct mutex pinctrl_mutex;
diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c
index 0c9d08d..fcc4bf4 100644
--- a/drivers/pinctrl/pinconf.c
+++ b/drivers/pinctrl/pinconf.c
@@ -64,15 +64,23 @@ int pin_config_get(const char *dev_name, const char *name,
struct pinctrl_dev *pctldev;
int pin;
+ mutex_lock(&pinctrl_mutex);
+
pctldev = get_pinctrl_dev_from_devname(dev_name);
- if (!pctldev)
- return -EINVAL;
+ if (!pctldev) {
+ pin = -EINVAL;
+ goto unlock;
+ }
pin = pin_get_from_name(pctldev, name);
if (pin < 0)
- return pin;
+ goto unlock;
- return pin_config_get_for_pin(pctldev, pin, config);
+ pin = pin_config_get_for_pin(pctldev, pin, config);
+
+unlock:
+ mutex_unlock(&pinctrl_mutex);
+ return pin;
}
EXPORT_SYMBOL(pin_config_get);
@@ -110,17 +118,27 @@ int pin_config_set(const char *dev_name, const char *name,
unsigned long config)
{
struct pinctrl_dev *pctldev;
- int pin;
+ int pin, ret;
+
+ mutex_lock(&pinctrl_mutex);
pctldev = get_pinctrl_dev_from_devname(dev_name);
- if (!pctldev)
- return -EINVAL;
+ if (!pctldev) {
+ ret = -EINVAL;
+ goto unlock;
+ }
pin = pin_get_from_name(pctldev, name);
- if (pin < 0)
- return pin;
+ if (pin < 0) {
+ ret = pin;
+ goto unlock;
+ }
+
+ ret = pin_config_set_for_pin(pctldev, pin, config);
- return pin_config_set_for_pin(pctldev, pin, config);
+unlock:
+ mutex_unlock(&pinctrl_mutex);
+ return ret;
}
EXPORT_SYMBOL(pin_config_set);
@@ -129,25 +147,36 @@ int pin_config_group_get(const char *dev_name, const char *pin_group,
{
struct pinctrl_dev *pctldev;
const struct pinconf_ops *ops;
- int selector;
+ int selector, ret;
+
+ mutex_lock(&pinctrl_mutex);
pctldev = get_pinctrl_dev_from_devname(dev_name);
- if (!pctldev)
- return -EINVAL;
+ if (!pctldev) {
+ ret = -EINVAL;
+ goto unlock;
+ }
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 "
"driver\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto unlock;
}
selector = pinctrl_get_group_selector(pctldev, pin_group);
- if (selector < 0)
- return selector;
+ if (selector < 0) {
+ ret = selector;
+ goto unlock;
+ }
- return ops->pin_config_group_get(pctldev, selector, config);
+ ret = ops->pin_config_group_get(pctldev, selector, config);
+
+unlock:
+ mutex_unlock(&pinctrl_mutex);
+ return ret;
}
EXPORT_SYMBOL(pin_config_group_get);
@@ -163,27 +192,34 @@ int pin_config_group_set(const char *dev_name, const char *pin_group,
int ret;
int i;
+ mutex_lock(&pinctrl_mutex);
+
pctldev = get_pinctrl_dev_from_devname(dev_name);
- if (!pctldev)
- return -EINVAL;
+ if (!pctldev) {
+ ret = -EINVAL;
+ goto unlock;
+ }
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");
- return -EINVAL;
+ ret = -EINVAL;
+ goto unlock;
}
selector = pinctrl_get_group_selector(pctldev, pin_group);
- if (selector < 0)
- return selector;
+ if (selector < 0) {
+ ret = selector;
+ goto unlock;
+ }
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;
+ goto unlock;
}
/*
@@ -197,23 +233,30 @@ int pin_config_group_set(const char *dev_name, const char *pin_group,
* pin-by-pin as well, it returns -EAGAIN.
*/
if (ret != -EAGAIN)
- return ret;
+ goto unlock;
}
/*
* If the controller cannot handle entire groups, we configure each pin
* individually.
*/
- if (!ops->pin_config_set)
- return 0;
+ if (!ops->pin_config_set) {
+ ret = 0;
+ goto unlock;
+ }
for (i = 0; i < num_pins; i++) {
ret = ops->pin_config_set(pctldev, pins[i], config);
if (ret < 0)
- return ret;
+ goto unlock;
}
- return 0;
+ ret = 0;
+
+unlock:
+ mutex_unlock(&pinctrl_mutex);
+
+ return ret;
}
EXPORT_SYMBOL(pin_config_group_set);
@@ -236,6 +279,8 @@ static int pinconf_pins_show(struct seq_file *s, void *what)
seq_puts(s, "Pin config settings per pin\n");
seq_puts(s, "Format: pin (name): pinmux setting array\n");
+ mutex_lock(&pinctrl_mutex);
+
/* The pin number can be retrived from the pin controller descriptor */
for (i = 0; i < pctldev->desc->npins; i++) {
struct pin_desc *desc;
@@ -254,6 +299,8 @@ static int pinconf_pins_show(struct seq_file *s, void *what)
seq_printf(s, "\n");
}
+ mutex_unlock(&pinctrl_mutex);
+
return 0;
}
@@ -280,6 +327,8 @@ static int pinconf_groups_show(struct seq_file *s, void *what)
seq_puts(s, "Pin config settings per pin group\n");
seq_puts(s, "Format: group (name): pinmux setting array\n");
+ mutex_lock(&pinctrl_mutex);
+
while (pctlops->list_groups(pctldev, selector) >= 0) {
const char *gname = pctlops->get_group_name(pctldev, selector);
@@ -288,6 +337,8 @@ static int pinconf_groups_show(struct seq_file *s, void *what)
selector++;
}
+ mutex_unlock(&pinctrl_mutex);
+
return 0;
}
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c
index 98b89d6..c574751 100644
--- a/drivers/pinctrl/pinmux.c
+++ b/drivers/pinctrl/pinmux.c
@@ -19,8 +19,6 @@
#include <linux/radix-tree.h>
#include <linux/err.h>
#include <linux/list.h>
-#include <linux/mutex.h>
-#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/sysfs.h>
#include <linux/debugfs.h>
@@ -93,15 +91,12 @@ static int pin_request(struct pinctrl_dev *pctldev,
goto out;
}
- spin_lock(&desc->lock);
if (desc->owner && strcmp(desc->owner, owner)) {
- spin_unlock(&desc->lock);
dev_err(pctldev->dev,
"pin already requested\n");
goto out;
}
desc->owner = owner;
- spin_unlock(&desc->lock);
/* Let each pin increase references to this module */
if (!try_module_get(pctldev->owner)) {
@@ -128,11 +123,8 @@ static int pin_request(struct pinctrl_dev *pctldev,
dev_err(pctldev->dev, "->request on device %s failed for pin %d\n",
pctldev->desc->name, pin);
out_free_pin:
- if (status) {
- spin_lock(&desc->lock);
+ if (status)
desc->owner = NULL;
- spin_unlock(&desc->lock);
- }
out:
if (status)
dev_err(pctldev->dev, "pin-%d (%s) status %d\n",
@@ -175,10 +167,8 @@ static const char *pin_free(struct pinctrl_dev *pctldev, int pin,
else if (ops->free)
ops->free(pctldev, pin);
- spin_lock(&desc->lock);
owner = desc->owner;
desc->owner = NULL;
- spin_unlock(&desc->lock);
module_put(pctldev->owner);
return owner;
@@ -590,6 +580,8 @@ static int pinmux_functions_show(struct seq_file *s, void *what)
const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
unsigned func_selector = 0;
+ mutex_lock(&pinctrl_mutex);
+
while (pmxops->list_functions(pctldev, func_selector) >= 0) {
const char *func = pmxops->get_function_name(pctldev,
func_selector);
@@ -610,9 +602,10 @@ static int pinmux_functions_show(struct seq_file *s, void *what)
seq_puts(s, "]\n");
func_selector++;
-
}
+ mutex_unlock(&pinctrl_mutex);
+
return 0;
}
@@ -624,9 +617,10 @@ static int pinmux_pins_show(struct seq_file *s, void *what)
seq_puts(s, "Pinmux settings per pin\n");
seq_puts(s, "Format: pin (name): owner\n");
+ mutex_lock(&pinctrl_mutex);
+
/* The pin number can be retrived from the pin controller descriptor */
for (i = 0; i < pctldev->desc->npins; i++) {
-
struct pin_desc *desc;
pin = pctldev->desc->pins[i].number;
@@ -640,6 +634,8 @@ static int pinmux_pins_show(struct seq_file *s, void *what)
desc->owner ? desc->owner : "UNCLAIMED");
}
+ mutex_unlock(&pinctrl_mutex);
+
return 0;
}
diff --git a/include/linux/pinctrl/pinctrl.h b/include/linux/pinctrl/pinctrl.h
index 8bd22ee..9ab4143 100644
--- a/include/linux/pinctrl/pinctrl.h
+++ b/include/linux/pinctrl/pinctrl.h
@@ -15,7 +15,6 @@
#ifdef CONFIG_PINCTRL
#include <linux/radix-tree.h>
-#include <linux/spinlock.h>
#include <linux/list.h>
#include <linux/seq_file.h>
--
1.7.5.4
pinconf_groups_show() wrote all debug information on one line. Fix it to
match pinconf_pins_show() and be legible.
Signed-off-by: Stephen Warren <[email protected]>
---
drivers/pinctrl/pinconf.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c
index fcc4bf4..e0a4537 100644
--- a/drivers/pinctrl/pinconf.c
+++ b/drivers/pinctrl/pinconf.c
@@ -334,6 +334,8 @@ static int pinconf_groups_show(struct seq_file *s, void *what)
seq_printf(s, "%u (%s):", selector, gname);
pinconf_dump_group(pctldev, s, selector, gname);
+ seq_printf(s, "\n");
+
selector++;
}
--
1.7.5.4
When pins are requested/acquired/got, some device becomes the owner of
their mux setting. At this point, it isn't certain which mux function
will be selected for the pin, since this may vary between each of the
device's states in the pinctrl mapping table. As such, we should record
the owning device, not what we think the initial mux setting will be,
when requesting pins.
This doesn't make a lot of difference right now since pinctrl_get gets
only one single device/state combination, but this will make a difference
when pinctrl_get gets all states, and pinctrl_select_state can switch
between states.
Signed-off-by: Stephen Warren <[email protected]>
---
drivers/pinctrl/core.h | 2 +-
drivers/pinctrl/pinmux.c | 71 ++++++++++++++++++++--------------------------
2 files changed, 32 insertions(+), 41 deletions(-)
diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h
index a50cdb0..de4c3ed 100644
--- a/drivers/pinctrl/core.h
+++ b/drivers/pinctrl/core.h
@@ -94,7 +94,7 @@ struct pin_desc {
spinlock_t lock;
/* These fields only added when supporting pinmux drivers */
#ifdef CONFIG_PINMUX
- const char *mux_function;
+ const char *owner;
#endif
};
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c
index 5a09cd2..24c4de1 100644
--- a/drivers/pinctrl/pinmux.c
+++ b/drivers/pinctrl/pinmux.c
@@ -43,21 +43,20 @@ struct pinmux_group {
/**
* pin_request() - request a single pin to be muxed in, typically for GPIO
* @pin: the pin number in the global pin space
- * @function: a functional name to give to this pin, passed to the driver
- * so it knows what function to mux in, e.g. the string "gpioNN"
- * means that you want to mux in the pin for use as GPIO number NN
+ * @owner: a representation of the owner of this pin; typically the device
+ * name that controls its mux function, or the requested GPIO name
* @gpio_range: the range matching the GPIO pin if this is a request for a
* single GPIO pin
*/
static int pin_request(struct pinctrl_dev *pctldev,
- int pin, const char *function,
+ int pin, const char *owner,
struct pinctrl_gpio_range *gpio_range)
{
struct pin_desc *desc;
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, owner);
desc = pin_desc_get(pctldev, pin);
if (desc == NULL) {
@@ -66,19 +65,14 @@ static int pin_request(struct pinctrl_dev *pctldev,
goto out;
}
- if (!function) {
- dev_err(pctldev->dev, "no function name given\n");
- return -EINVAL;
- }
-
spin_lock(&desc->lock);
- if (desc->mux_function) {
+ if (desc->owner && strcmp(desc->owner, owner)) {
spin_unlock(&desc->lock);
dev_err(pctldev->dev,
"pin already requested\n");
goto out;
}
- desc->mux_function = function;
+ desc->owner = owner;
spin_unlock(&desc->lock);
/* Let each pin increase references to this module */
@@ -108,13 +102,13 @@ static int pin_request(struct pinctrl_dev *pctldev,
out_free_pin:
if (status) {
spin_lock(&desc->lock);
- desc->mux_function = NULL;
+ desc->owner = NULL;
spin_unlock(&desc->lock);
}
out:
if (status)
dev_err(pctldev->dev, "pin-%d (%s) status %d\n",
- pin, function ? : "?", status);
+ pin, owner, status);
return status;
}
@@ -126,8 +120,8 @@ out:
* @gpio_range: the range matching the GPIO pin if this is a request for a
* single GPIO pin
*
- * This function returns a pointer to the function name in use. This is used
- * for callers that dynamically allocate a function name so it can be freed
+ * This function returns a pointer to the previous owner. This is used
+ * for callers that dynamically allocate an owner name so it can be freed
* once the pin is free. This is done for GPIO request functions.
*/
static const char *pin_free(struct pinctrl_dev *pctldev, int pin,
@@ -135,7 +129,7 @@ static const char *pin_free(struct pinctrl_dev *pctldev, int pin,
{
const struct pinmux_ops *ops = pctldev->desc->pmxops;
struct pin_desc *desc;
- const char *func;
+ const char *owner;
desc = pin_desc_get(pctldev, pin);
if (desc == NULL) {
@@ -154,12 +148,12 @@ static const char *pin_free(struct pinctrl_dev *pctldev, int pin,
ops->free(pctldev, pin);
spin_lock(&desc->lock);
- func = desc->mux_function;
- desc->mux_function = NULL;
+ owner = desc->owner;
+ desc->owner = NULL;
spin_unlock(&desc->lock);
module_put(pctldev->owner);
- return func;
+ return owner;
}
/**
@@ -173,19 +167,19 @@ int pinmux_request_gpio(struct pinctrl_dev *pctldev,
unsigned pin, unsigned gpio)
{
char gpiostr[16];
- const char *function;
+ const char *owner;
int ret;
/* Conjure some name stating what chip and pin this is taken by */
snprintf(gpiostr, 15, "%s:%d", range->name, gpio);
- function = kstrdup(gpiostr, GFP_KERNEL);
- if (!function)
+ owner = kstrdup(gpiostr, GFP_KERNEL);
+ if (!owner)
return -EINVAL;
- ret = pin_request(pctldev, pin, function, range);
+ ret = pin_request(pctldev, pin, owner, range);
if (ret < 0)
- kfree(function);
+ kfree(owner);
return ret;
}
@@ -199,10 +193,10 @@ int pinmux_request_gpio(struct pinctrl_dev *pctldev,
void pinmux_free_gpio(struct pinctrl_dev *pctldev, unsigned pin,
struct pinctrl_gpio_range *range)
{
- const char *func;
+ const char *owner;
- func = pin_free(pctldev, pin, range);
- kfree(func);
+ owner = pin_free(pctldev, pin, range);
+ kfree(owner);
}
/**
@@ -232,17 +226,15 @@ int pinmux_gpio_direction(struct pinctrl_dev *pctldev,
/**
* acquire_pins() - acquire all the pins for a certain function on a pinmux
* @pctldev: the device to take the pins on
- * @func_selector: the function selector to acquire the pins for
+ * @owner: a representation of the owner of this pin; typically the device
+ * name that controls its mux function
* @group_selector: the group selector containing the pins to acquire
*/
static int acquire_pins(struct pinctrl_dev *pctldev,
- unsigned func_selector,
+ const char *owner,
unsigned group_selector)
{
const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
- const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
- const char *func = pmxops->get_function_name(pctldev,
- func_selector);
const unsigned *pins;
unsigned num_pins;
int ret;
@@ -258,11 +250,11 @@ static int acquire_pins(struct pinctrl_dev *pctldev,
/* Try to allocate all pins in this group, one by one */
for (i = 0; i < num_pins; i++) {
- ret = pin_request(pctldev, pins[i], func, NULL);
+ ret = pin_request(pctldev, pins[i], owner, NULL);
if (ret) {
dev_err(pctldev->dev,
- "could not get pin %d for function %s on device %s - conflicting mux mappings?\n",
- pins[i], func ? : "(undefined)",
+ "could not get request pin %d on device %s - conflicting mux mappings?\n",
+ pins[i],
pinctrl_dev_get_name(pctldev));
/* On error release all taken pins */
i--; /* this pin just failed */
@@ -475,7 +467,7 @@ static int pinmux_enable_muxmap(struct pinctrl_dev *pctldev,
if (!grp)
return -ENOMEM;
grp->group_selector = group_selector;
- ret = acquire_pins(pctldev, func_selector, group_selector);
+ ret = acquire_pins(pctldev, devname, group_selector);
if (ret) {
kfree(grp);
return ret;
@@ -630,7 +622,7 @@ static int pinmux_pins_show(struct seq_file *s, void *what)
unsigned i, pin;
seq_puts(s, "Pinmux settings per pin\n");
- seq_puts(s, "Format: pin (name): pinmuxfunction\n");
+ seq_puts(s, "Format: pin (name): owner\n");
/* The pin number can be retrived from the pin controller descriptor */
for (i = 0; i < pctldev->desc->npins; i++) {
@@ -645,8 +637,7 @@ static int pinmux_pins_show(struct seq_file *s, void *what)
seq_printf(s, "pin %d (%s): %s\n", pin,
desc->name ? desc->name : "unnamed",
- desc->mux_function ? desc->mux_function
- : "UNCLAIMED");
+ desc->owner ? desc->owner : "UNCLAIMED");
}
return 0;
--
1.7.5.4
Instead of storing a single array of mapping table entries, which
requires realloc()ing that array each time it's extended and copying
the new data, simply store a list of pointers to the individual chunks.
This also removes the need to copy the mapping table at all; a pointer
is maintained to the original table, this saving memory.
A macro for_each_maps() is introduced to hide the additional complexity
of iterating over the map entries.
This change will also simplify removing chunks of entries from the mapping
table. This isn't important right now, but will be in the future, when
mapping table entries are dynamically added when parsing them from the
device tree, and removed when drivers no longer need to interact with
pinctrl.
Signed-off-by: Stephen Warren <[email protected]>
---
v2: Fixed kzalloc size parameter in pinctrl_register_mappings(),
add pr_error on kzalloc() failure, keep pinctrl_get() docs with
pinctrl_get() not pinctrl_get_locked(), make pinctrl_get_locked()
static, use list_add_tail instead of list_add, continue to duplicate
mapping table, don't remove __initdata from u300 mapping table.
---
drivers/pinctrl/core.c | 120 ++++++++++++++++++++++++++++++------------------
1 files changed, 75 insertions(+), 45 deletions(-)
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index feadf1c..50bcc51 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -7,6 +7,8 @@
*
* Author: Linus Walleij <[email protected]>
*
+ * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
+ *
* License terms: GNU General Public License (GPL) version 2
*/
#define pr_fmt(fmt) "pinctrl core: " fmt
@@ -31,6 +33,18 @@
#include "pinconf.h"
/**
+ * struct pinctrl_maps - a list item containing part of the mapping table
+ * @node: mapping table list node
+ * @maps: array of mapping table entries
+ * @num_maps: the number of entries in @maps
+ */
+struct pinctrl_maps {
+ struct list_head node;
+ struct pinctrl_map const *maps;
+ unsigned num_maps;
+};
+
+/**
* struct pinctrl_hog - a list item to stash control hogs
* @node: pin control hog list node
* @map: map entry responsible for this hogging
@@ -51,8 +65,14 @@ static DEFINE_MUTEX(pinctrl_list_mutex);
static LIST_HEAD(pinctrl_list);
/* Global pinctrl maps */
-static struct pinctrl_map *pinctrl_maps;
-static unsigned pinctrl_maps_num;
+static DEFINE_MUTEX(pinctrl_maps_mutex);
+static LIST_HEAD(pinctrl_maps);
+
+#define for_each_maps(_maps_node_, _i_, _map_) \
+ list_for_each_entry(_maps_node_, &pinctrl_maps, node) \
+ for (_i_ = 0, _map_ = &_maps_node_->maps[_i_]; \
+ _i_ < _maps_node_->num_maps; \
+ i++, _map_ = &_maps_node_->maps[_i_])
const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev)
{
@@ -454,23 +474,17 @@ int pinctrl_gpio_direction_output(unsigned gpio)
}
EXPORT_SYMBOL_GPL(pinctrl_gpio_direction_output);
-/**
- * pinctrl_get() - retrieves the pin controller handle for a certain device
- * @dev: the device to get the pin controller handle for
- * @name: an optional specific control mapping name or NULL, the name is only
- * needed if you want to have more than one mapping per device, or if you
- * need an anonymous pin control (not tied to any specific device)
- */
-struct pinctrl *pinctrl_get(struct device *dev, const char *name)
+static struct pinctrl *pinctrl_get_locked(struct device *dev, const char *name)
{
- struct pinctrl_map const *map = NULL;
struct pinctrl_dev *pctldev = NULL;
const char *devname = NULL;
struct pinctrl *p;
bool found_map;
unsigned num_maps = 0;
int ret = -ENODEV;
+ struct pinctrl_maps *maps_node;
int i;
+ struct pinctrl_map const *map;
/* We must have dev or ID or both */
if (!dev && !name)
@@ -494,8 +508,7 @@ struct pinctrl *pinctrl_get(struct device *dev, const char *name)
pinmux_init_pinctrl_handle(p);
/* Iterate over the pin control maps to locate the right ones */
- for (i = 0; i < pinctrl_maps_num; i++) {
- map = &pinctrl_maps[i];
+ for_each_maps(maps_node, i, map) {
found_map = false;
/*
@@ -515,7 +528,6 @@ struct pinctrl *pinctrl_get(struct device *dev, const char *name)
pr_debug("in map, found pctldev %s to handle function %s",
dev_name(pctldev->dev), map->function);
-
/*
* If we're looking for a specific named map, this must match,
* else we loop and look for the next.
@@ -574,6 +586,24 @@ struct pinctrl *pinctrl_get(struct device *dev, const char *name)
return p;
}
+
+/**
+ * pinctrl_get() - retrieves the pin controller handle for a certain device
+ * @dev: the device to get the pin controller handle for
+ * @name: an optional specific control mapping name or NULL, the name is only
+ * needed if you want to have more than one mapping per device, or if you
+ * need an anonymous pin control (not tied to any specific device)
+ */
+struct pinctrl *pinctrl_get(struct device *dev, const char *name)
+{
+ struct pinctrl *p;
+
+ mutex_lock(&pinctrl_maps_mutex);
+ p = pinctrl_get_locked(dev, name);
+ mutex_unlock(&pinctrl_maps_mutex);
+
+ return p;
+}
EXPORT_SYMBOL_GPL(pinctrl_get);
/**
@@ -649,8 +679,8 @@ EXPORT_SYMBOL_GPL(pinctrl_disable);
int pinctrl_register_mappings(struct pinctrl_map const *maps,
unsigned num_maps)
{
- void *tmp_maps;
int i;
+ struct pinctrl_maps *maps_node;
pr_debug("add %d pinmux maps\n", num_maps);
@@ -684,31 +714,23 @@ int pinctrl_register_mappings(struct pinctrl_map const *maps,
maps[i].function);
}
- /*
- * Make a copy of the map array - string pointers will end up in the
- * kernel const section anyway so these do not need to be deep copied.
- */
- if (!pinctrl_maps_num) {
- /* On first call, just copy them */
- tmp_maps = kmemdup(maps,
- sizeof(struct pinctrl_map) * num_maps,
- GFP_KERNEL);
- if (!tmp_maps)
- return -ENOMEM;
- } else {
- /* Subsequent calls, reallocate array to new size */
- size_t oldsize = sizeof(struct pinctrl_map) * pinctrl_maps_num;
- size_t newsize = sizeof(struct pinctrl_map) * num_maps;
+ maps_node = kzalloc(sizeof(*maps_node), GFP_KERNEL);
+ if (!maps_node) {
+ pr_err("failed to alloc struct pinctrl_maps\n");
+ return -ENOMEM;
+ }
- tmp_maps = krealloc(pinctrl_maps,
- oldsize + newsize, GFP_KERNEL);
- if (!tmp_maps)
- return -ENOMEM;
- memcpy((tmp_maps + oldsize), maps, newsize);
+ maps_node->num_maps = num_maps;
+ maps_node->maps = kmemdup(maps, sizeof(*maps) * num_maps, GFP_KERNEL);
+ if (!maps_node->maps) {
+ kfree(maps_node);
+ return -ENOMEM;
}
- pinctrl_maps = tmp_maps;
- pinctrl_maps_num += num_maps;
+ mutex_lock(&pinctrl_maps_mutex);
+ list_add_tail(&maps_node->node, &pinctrl_maps);
+ mutex_unlock(&pinctrl_maps_mutex);
+
return 0;
}
@@ -724,7 +746,7 @@ static int pinctrl_hog_map(struct pinctrl_dev *pctldev,
if (!hog)
return -ENOMEM;
- p = pinctrl_get(pctldev->dev, map->name);
+ p = pinctrl_get_locked(pctldev->dev, map->name);
if (IS_ERR(p)) {
kfree(hog);
dev_err(pctldev->dev,
@@ -768,23 +790,28 @@ int pinctrl_hog_maps(struct pinctrl_dev *pctldev)
struct device *dev = pctldev->dev;
const char *devname = dev_name(dev);
int ret;
+ struct pinctrl_maps *maps_node;
int i;
+ struct pinctrl_map const *map;
INIT_LIST_HEAD(&pctldev->pinctrl_hogs);
mutex_init(&pctldev->pinctrl_hogs_lock);
- for (i = 0; i < pinctrl_maps_num; i++) {
- struct pinctrl_map const *map = &pinctrl_maps[i];
-
+ mutex_lock(&pinctrl_maps_mutex);
+ for_each_maps(maps_node, i, map) {
if (map->ctrl_dev_name &&
!strcmp(map->ctrl_dev_name, devname) &&
!strcmp(map->dev_name, devname)) {
/* OK time to hog! */
ret = pinctrl_hog_map(pctldev, map);
- if (ret)
+ if (ret) {
+ mutex_unlock(&pinctrl_maps_mutex);
return ret;
+ }
}
}
+ mutex_unlock(&pinctrl_maps_mutex);
+
return 0;
}
@@ -900,13 +927,14 @@ static int pinctrl_gpioranges_show(struct seq_file *s, void *what)
static int pinctrl_maps_show(struct seq_file *s, void *what)
{
+ struct pinctrl_maps *maps_node;
int i;
+ struct pinctrl_map const *map;
seq_puts(s, "Pinctrl maps:\n");
- for (i = 0; i < pinctrl_maps_num; i++) {
- struct pinctrl_map const *map = &pinctrl_maps[i];
-
+ mutex_lock(&pinctrl_maps_mutex);
+ for_each_maps(maps_node, i, map) {
seq_printf(s, "%s:\n", map->name);
if (map->dev_name)
seq_printf(s, " device: %s\n",
@@ -919,6 +947,8 @@ static int pinctrl_maps_show(struct seq_file *s, void *what)
seq_printf(s, " group: %s\n", map->group ? map->group :
"(default)");
}
+ mutex_unlock(&pinctrl_maps_mutex);
+
return 0;
}
--
1.7.5.4
The pinctrl mapping table can now contain entries to:
* Set the mux function of a pin group
* Apply a set of pin config options to a pin or a group
This allows pinctrl_select_state() to apply pin configs settings as well
as mux settings.
Signed-off-by: Stephen Warren <[email protected]>
---
Documentation/pinctrl.txt | 76 ++++++++++++++---
arch/arm/mach-u300/core.c | 12 ++--
drivers/pinctrl/core.c | 177 +++++++++++++++++++++++++++++++++------
drivers/pinctrl/core.h | 37 +++++++-
drivers/pinctrl/pinconf.c | 164 ++++++++++++++++++++++++++++++++++++
drivers/pinctrl/pinconf.h | 40 +++++++++
drivers/pinctrl/pinmux.c | 69 ++++++++++------
drivers/pinctrl/pinmux.h | 23 ++++-
include/linux/pinctrl/machine.h | 117 +++++++++++++++++++-------
9 files changed, 609 insertions(+), 106 deletions(-)
diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt
index cacd857..d69b7cd 100644
--- a/Documentation/pinctrl.txt
+++ b/Documentation/pinctrl.txt
@@ -206,14 +206,21 @@ 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:
+Pin configuration can be programmed either using the explicit APIs described
+immediately below, or by adding configuration entries into the mapping table;
+see section "Board/machine configuration" below.
+
+For example, a platform may do the following to pull up a pin to VDD:
#include <linux/pinctrl/consumer.h>
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:
+The format and meaning of the configuration parameter, PLATFORM_X_PULL_UP
+above, is entirely defined by the pin controller driver.
+
+The pin configuration driver implements callbacks for changing pin
+configuration in the pin controller ops like this:
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinconf.h>
@@ -765,7 +772,7 @@ obtain the function "gpioN" where "N" is the global GPIO pin number if no
special GPIO-handler is registered.
-Pinmux board/machine configuration
+Board/machine configuration
==================================
Boards and machines define how a certain complete running system is put
@@ -773,9 +780,9 @@ together, including how GPIOs and devices are muxed, how regulators are
constrained and how the clock tree looks. Of course pinmux settings are also
part of this.
-A pinmux config for a machine looks pretty much like a simple regulator
-configuration, so for the example array above we want to enable i2c and
-spi on the second function mapping:
+A pin controller configuration for a machine looks pretty much like a simple
+regulator configuration, so for the example array above we want to enable i2c
+and spi on the second function mapping:
#include <linux/pinctrl/machine.h>
@@ -783,20 +790,23 @@ static const struct pinctrl_map __initdata mapping[] = {
{
.dev_name = "foo-spi.0",
.name = "default",
+ .type = PIN_MAP_TYPE_MUX_GROUP,
.ctrl_dev_name = "pinctrl-foo",
- .function = "spi0",
+ .data.mux.function = "spi0",
},
{
.dev_name = "foo-i2c.0",
.name = "default",
+ .type = PIN_MAP_TYPE_MUX_GROUP,
.ctrl_dev_name = "pinctrl-foo",
- .function = "i2c0",
+ .data.mux.function = "i2c0",
},
{
.dev_name = "foo-mmc.0",
.name = "default",
+ .type = PIN_MAP_TYPE_MUX_GROUP,
.ctrl_dev_name = "pinctrl-foo",
- .function = "mmc0",
+ .data.mux.function = "mmc0",
},
};
@@ -817,7 +827,40 @@ it even more compact which assumes you want to use pinctrl-foo and position
0 for mapping, for example:
static struct pinctrl_map __initdata mapping[] = {
- PIN_MAP("default", "pinctrl-foo", "i2c0", "foo-i2c.0"),
+ PIN_MAP_MUX_GROUP("foo-i2c.o", "default", "pinctrl-foo", NULL, "i2c0"),
+};
+
+The mapping table may also contain pin configuration entries. It's common for
+each pin/group to have a number of configuration entries that affect it, so
+the table entries for configuration reference an array of config parameters
+and values. An example using the convenience macros is shown below:
+
+static unsigned long i2c_grp_configs[] = {
+ FOO_PIN_DRIVEN,
+ FOO_PIN_PULLUP,
+};
+
+static unsigned long i2c_pin_configs[] = {
+ FOO_OPEN_COLLECTOR,
+ FOO_SLEW_RATE_SLOW,
+};
+
+static struct pinctrl_map __initdata mapping[] = {
+ PIN_MAP_MUX_GROUP("foo-i2c.0", "default", "pinctrl-foo", "i2c0", "i2c0"),
+ PIN_MAP_MUX_CONFIGS_GROUP("foo-i2c.0", "default", "pinctrl-foo", "i2c0", i2c_grp_configs),
+ PIN_MAP_MUX_CONFIGS_PIN("foo-i2c.0", "default", "pinctrl-foo", "i2c0scl", i2c_pin_configs),
+ PIN_MAP_MUX_CONFIGS_PIN("foo-i2c.0", "default", "pinctrl-foo", "i2c0sda", i2c_pin_configs),
+};
+
+Finally, some devices expect the mapping table to contain certain specific
+named states. When running on hardware that doesn't need any pin controller
+configuration, the mapping table must still contain those named states, in
+order to explicitly indicate that the states were provided and intended to
+be empty. Table entry macro PIN_MAP_DUMMY_STATE serves the purpose of defining
+a named state without causing any pin controller to be programmed:
+
+static struct pinctrl_map __initdata mapping[] = {
+ PIN_MAP_DUMMY_STATE("foo-i2c.0", "default"),
};
@@ -831,6 +874,7 @@ As it is possible to map a function to different groups of pins an optional
{
.dev_name = "foo-spi.0",
.name = "spi0-pos-A",
+ .type = PIN_MAP_TYPE_MUX_GROUP,
.ctrl_dev_name = "pinctrl-foo",
.function = "spi0",
.group = "spi0_0_grp",
@@ -838,6 +882,7 @@ As it is possible to map a function to different groups of pins an optional
{
.dev_name = "foo-spi.0",
.name = "spi0-pos-B",
+ .type = PIN_MAP_TYPE_MUX_GROUP,
.ctrl_dev_name = "pinctrl-foo",
.function = "spi0",
.group = "spi0_1_grp",
@@ -857,6 +902,7 @@ case), we define a mapping like this:
{
.dev_name = "foo-mmc.0",
.name = "2bit"
+ .type = PIN_MAP_TYPE_MUX_GROUP,
.ctrl_dev_name = "pinctrl-foo",
.function = "mmc0",
.group = "mmc0_1_grp",
@@ -864,6 +910,7 @@ case), we define a mapping like this:
{
.dev_name = "foo-mmc.0",
.name = "4bit"
+ .type = PIN_MAP_TYPE_MUX_GROUP,
.ctrl_dev_name = "pinctrl-foo",
.function = "mmc0",
.group = "mmc0_1_grp",
@@ -871,6 +918,7 @@ case), we define a mapping like this:
{
.dev_name = "foo-mmc.0",
.name = "4bit"
+ .type = PIN_MAP_TYPE_MUX_GROUP,
.ctrl_dev_name = "pinctrl-foo",
.function = "mmc0",
.group = "mmc0_2_grp",
@@ -878,6 +926,7 @@ case), we define a mapping like this:
{
.dev_name = "foo-mmc.0",
.name = "8bit"
+ .type = PIN_MAP_TYPE_MUX_GROUP,
.ctrl_dev_name = "pinctrl-foo",
.function = "mmc0",
.group = "mmc0_1_grp",
@@ -885,6 +934,7 @@ case), we define a mapping like this:
{
.dev_name = "foo-mmc.0",
.name = "8bit"
+ .type = PIN_MAP_TYPE_MUX_GROUP,
.ctrl_dev_name = "pinctrl-foo",
.function = "mmc0",
.group = "mmc0_2_grp",
@@ -892,6 +942,7 @@ case), we define a mapping like this:
{
.dev_name = "foo-mmc.0",
.name = "8bit"
+ .type = PIN_MAP_TYPE_MUX_GROUP,
.ctrl_dev_name = "pinctrl-foo",
.function = "mmc0",
.group = "mmc0_3_grp",
@@ -1014,6 +1065,7 @@ to the pin controller device name, and the state name is "active".
{
.dev_name = "pinctrl-foo",
.name = "active",
+ .type = PIN_MAP_TYPE_MUX_GROUP,
.ctrl_dev_name = "pinctrl-foo",
.function = "power_func",
},
@@ -1022,7 +1074,7 @@ Since it may be common to request the core to hog a few always-applicable
mux settings on the primary pin controller, there is a convenience macro for
this:
-PIN_MAP_SYS_HOG("active", "pinctrl-foo", "power_func")
+PIN_MAP_MUX_GROUP("pinctrl-foo", "active", "pinctrl-foo", NULL, "power_func")
This gives the exact same result as the above construction.
diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c
index eb79a49..599aa79 100644
--- a/arch/arm/mach-u300/core.c
+++ b/arch/arm/mach-u300/core.c
@@ -1554,13 +1554,13 @@ static struct platform_device pinmux_device = {
/* Pinmux settings */
static struct pinctrl_map __initdata u300_pinmux_map[] = {
/* anonymous maps for chip power and EMIFs */
- PIN_MAP_SYS_HOG("default", "pinmux-u300", "power"),
- PIN_MAP_SYS_HOG("default", "pinmux-u300", "emif0"),
- PIN_MAP_SYS_HOG("default", "pinmux-u300", "emif1"),
+ PIN_MAP_MUX_GROUP("pinmux-u300", "default", "pinmux-u300", NULL, "power"),
+ PIN_MAP_MUX_GROUP("pinmux-u300", "default", "pinmux-u300", NULL, "emif0"),
+ PIN_MAP_MUX_GROUP("pinmux-u300", "default", "pinmux-u300", NULL, "emif1"),
/* per-device maps for MMC/SD, SPI and UART */
- PIN_MAP("default", "pinmux-u300", "mmc0", "mmci"),
- PIN_MAP("default", "pinmux-u300", "spi0", "pl022"),
- PIN_MAP("default", "pinmux-u300", "uart0", "uart0"),
+ PIN_MAP_MUX_GROUP("mmci", "default", "pinmux-u300", NULL, "mmc0"),
+ PIN_MAP_MUX_GROUP("pl022", "default", "pinmux-u300", NULL, "spi0"),
+ PIN_MAP_MUX_GROUP("uart0", "default", "pinmux-u300", NULL, "uart0"),
};
struct u300_mux_hog {
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index bab1a69..af4ebe9 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -341,6 +341,31 @@ int pinctrl_get_group_selector(struct pinctrl_dev *pctldev,
}
/**
+ * pinctrl_get_pin_id() - returns the group selector for a group
+ * @pctldev: the pin controller handling the group
+ * @pin_group: the pin group to look up
+ */
+int pinctrl_get_pin_id(struct pinctrl_dev *pctldev,
+ const char *pin)
+{
+ unsigned int i;
+
+ for (i = 0; i < pctldev->desc->npins; i++) {
+ if (pctldev->desc->pins[i].name == NULL)
+ continue;
+ if (!strcmp(pin, pctldev->desc->pins[i].name)) {
+ dev_dbg(pctldev->dev, "found pin id %u for %s\n",
+ i, pin);
+ return i;
+ }
+ }
+
+ dev_err(pctldev->dev, "does not have pin %s\n", pin);
+
+ return -EINVAL;
+}
+
+/**
* pinctrl_request_gpio() - request a single pin to be used in as GPIO
* @gpio: the GPIO pin number from the GPIO subsystem number space
*
@@ -502,6 +527,9 @@ static int add_setting(struct pinctrl *p, struct pinctrl_map const *map)
if (IS_ERR(state))
return PTR_ERR(state);
+ if (map->type == PIN_MAP_TYPE_DUMMY_STATE)
+ return 0;
+
setting = kzalloc(sizeof(*setting), GFP_KERNEL);
if (setting == NULL) {
dev_err(p->dev,
@@ -509,6 +537,8 @@ static int add_setting(struct pinctrl *p, struct pinctrl_map const *map)
return -ENOMEM;
}
+ setting->type = map->type;
+
setting->pctldev = get_pinctrl_dev_from_devname(map->ctrl_dev_name);
if (setting->pctldev == NULL) {
dev_err(p->dev, "unknown pinctrl device %s in map entry",
@@ -518,7 +548,18 @@ static int add_setting(struct pinctrl *p, struct pinctrl_map const *map)
return -ENODEV;
}
- ret = pinmux_map_to_setting(map, setting);
+ switch (map->type) {
+ case PIN_MAP_TYPE_MUX_GROUP:
+ ret = pinmux_map_to_setting(map, setting);
+ break;
+ case PIN_MAP_TYPE_CONFIGS_PIN:
+ case PIN_MAP_TYPE_CONFIGS_GROUP:
+ ret = pinconf_map_to_setting(map, setting);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
if (ret < 0) {
kfree(setting);
return ret;
@@ -630,9 +671,19 @@ static void pinctrl_put_locked(struct pinctrl *p, bool inlist)
list_for_each_entry_safe(state, n1, &p->states, node) {
list_for_each_entry_safe(setting, n2, &state->settings, node) {
- if (state == p->state)
- pinmux_disable_setting(setting);
- pinmux_free_setting(setting);
+ switch (setting->type) {
+ case PIN_MAP_TYPE_MUX_GROUP:
+ if (state == p->state)
+ pinmux_disable_setting(setting);
+ pinmux_free_setting(setting);
+ break;
+ case PIN_MAP_TYPE_CONFIGS_PIN:
+ case PIN_MAP_TYPE_CONFIGS_GROUP:
+ pinconf_free_setting(setting);
+ break;
+ default:
+ break;
+ }
list_del(&setting->node);
kfree(setting);
}
@@ -707,9 +758,13 @@ static int pinctrl_select_state_locked(struct pinctrl *p,
*/
list_for_each_entry(setting, &p->state->settings, node) {
bool found = false;
+ if (setting->type != PIN_MAP_TYPE_MUX_GROUP)
+ continue;
list_for_each_entry(setting2, &state->settings, node) {
- if (setting2->group_selector ==
- setting->group_selector) {
+ if (setting2->type != PIN_MAP_TYPE_MUX_GROUP)
+ continue;
+ if (setting2->data.mux.group ==
+ setting->data.mux.group) {
found = true;
break;
}
@@ -723,7 +778,18 @@ static int pinctrl_select_state_locked(struct pinctrl *p,
/* Apply all the settings for the new state */
list_for_each_entry(setting, &state->settings, node) {
- ret = pinmux_enable_setting(setting);
+ switch (setting->type) {
+ case PIN_MAP_TYPE_MUX_GROUP:
+ ret = pinmux_enable_setting(setting);
+ break;
+ case PIN_MAP_TYPE_CONFIGS_PIN:
+ case PIN_MAP_TYPE_CONFIGS_GROUP:
+ ret = pinconf_apply_setting(setting);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
if (ret < 0) {
/* FIXME: Difficult to return to prev state */
return ret;
@@ -760,33 +826,48 @@ EXPORT_SYMBOL_GPL(pinctrl_select_state);
int pinctrl_register_mappings(struct pinctrl_map const *maps,
unsigned num_maps)
{
- int i;
+ int i, ret;
struct pinctrl_maps *maps_node;
pr_debug("add %d pinmux maps\n", num_maps);
/* First sanity check the new mapping */
for (i = 0; i < num_maps; i++) {
+ if (!maps[i].dev_name) {
+ pr_err("failed to register map %s (%d): no device given\n",
+ maps[i].name, i);
+ return -EINVAL;
+ }
+
if (!maps[i].name) {
pr_err("failed to register map %d: no map name given\n",
i);
return -EINVAL;
}
- if (!maps[i].ctrl_dev_name) {
+ if (maps[i].type != PIN_MAP_TYPE_DUMMY_STATE &&
+ !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;
}
- if (!maps[i].function) {
- pr_err("failed to register map %s (%d): no function ID given\n",
- maps[i].name, i);
- return -EINVAL;
- }
-
- if (!maps[i].dev_name) {
- pr_err("failed to register map %s (%d): no device given\n",
+ switch (maps[i].type) {
+ case PIN_MAP_TYPE_DUMMY_STATE:
+ break;
+ case PIN_MAP_TYPE_MUX_GROUP:
+ ret = pinmux_validate_map(&maps[i], i);
+ if (ret < 0)
+ return 0;
+ break;
+ case PIN_MAP_TYPE_CONFIGS_PIN:
+ case PIN_MAP_TYPE_CONFIGS_GROUP:
+ ret = pinconf_validate_map(&maps[i], i);
+ if (ret < 0)
+ return 0;
+ break;
+ default:
+ pr_err("failed to register map %s (%d): invalid type given\n",
maps[i].name, i);
return -EINVAL;
}
@@ -912,6 +993,22 @@ static int pinctrl_gpioranges_show(struct seq_file *s, void *what)
return 0;
}
+static inline const char *map_type(enum pinctrl_map_type type)
+{
+ static const char * const names[] = {
+ "INVALID",
+ "DUMMY_STATE",
+ "MUX_GROUP",
+ "CONFIGS_PIN",
+ "CONFIGS_GROUP",
+ };
+
+ if (type >= ARRAY_SIZE(names))
+ return "UNKNOWN";
+
+ return names[type];
+}
+
static int pinctrl_maps_show(struct seq_file *s, void *what)
{
struct pinctrl_maps *maps_node;
@@ -923,12 +1020,27 @@ static int pinctrl_maps_show(struct seq_file *s, void *what)
mutex_lock(&pinctrl_mutex);
for_each_maps(maps_node, i, map) {
- seq_printf(s, "%s:\n", map->name);
- seq_printf(s, " device: %s\n", map->dev_name);
- seq_printf(s, " controlling device %s\n", map->ctrl_dev_name);
- seq_printf(s, " function: %s\n", map->function);
- seq_printf(s, " group: %s\n", map->group ? map->group :
- "(default)");
+ seq_printf(s, "device %s\nstate %s\ntype %s (%d)\n",
+ map->dev_name, map->name, map_type(map->type),
+ map->type);
+
+ if (map->type != PIN_MAP_TYPE_MUX_GROUP)
+ seq_printf(s, "controlling device %s\n",
+ map->ctrl_dev_name);
+
+ switch (map->type) {
+ case PIN_MAP_TYPE_MUX_GROUP:
+ pinmux_show_map(s, map);
+ break;
+ case PIN_MAP_TYPE_CONFIGS_PIN:
+ case PIN_MAP_TYPE_CONFIGS_GROUP:
+ pinconf_show_map(s, map);
+ break;
+ default:
+ break;
+ }
+
+ seq_printf(s, "\n");
}
mutex_unlock(&pinctrl_mutex);
@@ -981,8 +1093,23 @@ static int pinctrl_show(struct seq_file *s, void *what)
seq_printf(s, " state: %s\n", state->name);
list_for_each_entry(setting, &state->settings, node) {
- seq_printf(s, " ");
- pinmux_dbg_show(s, setting);
+ struct pinctrl_dev *pctldev = setting->pctldev;
+
+ seq_printf(s, " type: %s controller %s ",
+ map_type(setting->type),
+ pinctrl_dev_get_name(pctldev));
+
+ switch (setting->type) {
+ case PIN_MAP_TYPE_MUX_GROUP:
+ pinmux_show_setting(s, setting);
+ break;
+ case PIN_MAP_TYPE_CONFIGS_PIN:
+ case PIN_MAP_TYPE_CONFIGS_GROUP:
+ pinconf_show_setting(s, setting);
+ break;
+ default:
+ break;
+ }
}
}
}
diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h
index d5bc9ea..e75a18a 100644
--- a/drivers/pinctrl/core.h
+++ b/drivers/pinctrl/core.h
@@ -75,17 +75,44 @@ struct pinctrl_state {
};
/**
+ * struct pinctrl_setting_mux - setting data for MAP_TYPE_MUX_GROUP
+ * @group: the group selector to program
+ * @func: the function selector to program
+ */
+struct pinctrl_setting_mux {
+ unsigned group;
+ unsigned func;
+};
+
+/**
+ * struct pinctrl_setting_configs - setting data for MAP_TYPE_CONFIGS_*
+ * @group_or_pin: the group selector or pin ID to program
+ * @configs: a pointer to an array of config parameters/values to program into
+ * hardware. Each individual pin controller defines the format and meaning
+ * of config parameters.
+ * @num_configs: the number of entries in array @configs
+ */
+struct pinctrl_setting_configs {
+ unsigned group_or_pin;
+ unsigned long *configs;
+ unsigned num_configs;
+};
+
+/**
* struct pinctrl_setting - an individual mux setting
* @node: list node for struct pinctrl_settings's @settings field
+ * @type: the type of setting
* @pctldev: pin control device handling to be programmed
- * @group_selector: the group selector to program
- * @func_selector: the function selector to program
+ * @data: Data specific to the setting type
*/
struct pinctrl_setting {
struct list_head node;
+ enum pinctrl_map_type type;
struct pinctrl_dev *pctldev;
- unsigned group_selector;
- unsigned func_selector;
+ union {
+ struct pinctrl_setting_mux mux;
+ struct pinctrl_setting_configs configs;
+ } data;
};
/**
@@ -113,6 +140,8 @@ struct pinctrl_dev *get_pinctrl_dev_from_devname(const char *dev_name);
int pin_get_from_name(struct pinctrl_dev *pctldev, const char *name);
int pinctrl_get_group_selector(struct pinctrl_dev *pctldev,
const char *pin_group);
+int pinctrl_get_pin_id(struct pinctrl_dev *pctldev,
+ const char *pin);
static inline struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev,
unsigned int pin)
diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c
index e0a4537..1de513b 100644
--- a/drivers/pinctrl/pinconf.c
+++ b/drivers/pinctrl/pinconf.c
@@ -36,6 +36,24 @@ int pinconf_check_ops(struct pinctrl_dev *pctldev)
return 0;
}
+int pinconf_validate_map(struct pinctrl_map const *map, int i)
+{
+ if (!map->data.configs.group_or_pin) {
+ pr_err("failed to register map %s (%d): no group/pin given\n",
+ map->name, i);
+ return -EINVAL;
+ }
+
+ if (map->data.configs.num_configs &&
+ !map->data.configs.configs) {
+ pr_err("failed to register map %s (%d): no configs ptr given\n",
+ map->name, i);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
unsigned long *config)
{
@@ -260,8 +278,154 @@ unlock:
}
EXPORT_SYMBOL(pin_config_group_set);
+int pinconf_map_to_setting(struct pinctrl_map const *map,
+ struct pinctrl_setting *setting)
+{
+ struct pinctrl_dev *pctldev = setting->pctldev;
+
+ switch (setting->type) {
+ case PIN_MAP_TYPE_CONFIGS_PIN:
+ setting->data.configs.group_or_pin =
+ pinctrl_get_pin_id(pctldev,
+ map->data.configs.group_or_pin);
+ if (setting->data.configs.group_or_pin < 0)
+ return setting->data.configs.group_or_pin;
+ break;
+ break;
+ case PIN_MAP_TYPE_CONFIGS_GROUP:
+ setting->data.configs.group_or_pin =
+ pinctrl_get_group_selector(pctldev,
+ map->data.configs.group_or_pin);
+ if (setting->data.configs.group_or_pin < 0)
+ return setting->data.configs.group_or_pin;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ setting->data.configs.num_configs = map->data.configs.num_configs;
+ setting->data.configs.configs = map->data.configs.configs;
+
+ return 0;
+}
+
+void pinconf_free_setting(struct pinctrl_setting const *setting)
+{
+}
+
+int pinconf_apply_setting(struct pinctrl_setting const *setting)
+{
+ struct pinctrl_dev *pctldev = setting->pctldev;
+ const struct pinconf_ops *ops = pctldev->desc->confops;
+ int i, ret;
+
+ if (!ops) {
+ dev_err(pctldev->dev, "missing confops\n");
+ return -EINVAL;
+ }
+
+ switch (setting->type) {
+ case PIN_MAP_TYPE_CONFIGS_PIN:
+ if (!ops->pin_config_set) {
+ dev_err(pctldev->dev, "missing pin_config_set op\n");
+ return -EINVAL;
+ }
+ for (i = 0; i < setting->data.configs.num_configs; i++) {
+ ret = ops->pin_config_set(pctldev,
+ setting->data.configs.group_or_pin,
+ setting->data.configs.configs[i]);
+ if (ret < 0)
+ dev_err(pctldev->dev,
+ "pin_config_set op failed for pin %d config %08lx\n",
+ setting->data.configs.group_or_pin,
+ setting->data.configs.configs[i]);
+ return ret;
+ }
+ break;
+ case PIN_MAP_TYPE_CONFIGS_GROUP:
+ if (!ops->pin_config_group_set) {
+ dev_err(pctldev->dev,
+ "missing pin_config_group_set op\n");
+ return -EINVAL;
+ }
+ for (i = 0; i < setting->data.configs.num_configs; i++) {
+ ret = ops->pin_config_group_set(pctldev,
+ setting->data.configs.group_or_pin,
+ setting->data.configs.configs[i]);
+ if (ret < 0)
+ dev_err(pctldev->dev,
+ "pin_config_group_set op failed for group %d config %08lx\n",
+ setting->data.configs.group_or_pin,
+ setting->data.configs.configs[i]);
+ return ret;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
#ifdef CONFIG_DEBUG_FS
+void pinconf_show_map(struct seq_file *s, struct pinctrl_map const *map)
+{
+ int i;
+
+ switch (map->type) {
+ case PIN_MAP_TYPE_CONFIGS_PIN:
+ seq_printf(s, "pin ");
+ break;
+ case PIN_MAP_TYPE_CONFIGS_GROUP:
+ seq_printf(s, "group ");
+ break;
+ default:
+ break;
+ }
+
+ seq_printf(s, "%s\n", map->data.configs.group_or_pin);
+
+ for (i = 0; i < map->data.configs.num_configs; i++)
+ seq_printf(s, "config %08lx\n", map->data.configs.configs[i]);
+}
+
+void pinconf_show_setting(struct seq_file *s,
+ struct pinctrl_setting const *setting)
+{
+ struct pinctrl_dev *pctldev = setting->pctldev;
+ const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
+ struct pin_desc *desc;
+ int i;
+
+ switch (setting->type) {
+ case PIN_MAP_TYPE_CONFIGS_PIN:
+ desc = pin_desc_get(setting->pctldev,
+ setting->data.configs.group_or_pin);
+ seq_printf(s, "pin %s (%d)",
+ desc->name ? desc->name : "unnamed",
+ setting->data.configs.group_or_pin);
+ break;
+ case PIN_MAP_TYPE_CONFIGS_GROUP:
+ seq_printf(s, "group %s (%d)",
+ pctlops->get_group_name(pctldev,
+ setting->data.configs.group_or_pin),
+ setting->data.configs.group_or_pin);
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * FIXME: We should really get the pin controler to dump the config
+ * values, so they can be decoded to something meaningful.
+ */
+ for (i = 0; i < setting->data.configs.num_configs; i++)
+ seq_printf(s, " %08lx", setting->data.configs.configs[i]);
+
+ seq_printf(s, "\n");
+}
+
static void pinconf_dump_pin(struct pinctrl_dev *pctldev,
struct seq_file *s, int pin)
{
diff --git a/drivers/pinctrl/pinconf.h b/drivers/pinctrl/pinconf.h
index 1d6ea9d..0ded227 100644
--- a/drivers/pinctrl/pinconf.h
+++ b/drivers/pinctrl/pinconf.h
@@ -15,6 +15,16 @@
int pinconf_check_ops(struct pinctrl_dev *pctldev);
+int pinconf_validate_map(struct pinctrl_map const *map, int i);
+
+int pinconf_map_to_setting(struct pinctrl_map const *map,
+ struct pinctrl_setting *setting);
+void pinconf_free_setting(struct pinctrl_setting const *setting);
+int pinconf_apply_setting(struct pinctrl_setting const *setting);
+
+void pinconf_show_map(struct seq_file *s, struct pinctrl_map const *map);
+void pinconf_show_setting(struct seq_file *s,
+ struct pinctrl_setting const *setting);
void pinconf_init_device_debugfs(struct dentry *devroot,
struct pinctrl_dev *pctldev);
@@ -25,6 +35,36 @@ static inline int pinconf_check_ops(struct pinctrl_dev *pctldev)
return 0;
}
+static inline int pinconf_validate_map(struct pinctrl_map const *map, int i)
+{
+ return 0;
+}
+
+static inline int pinconf_map_to_setting(struct pinctrl_map const *map,
+ struct pinctrl_setting *setting)
+{
+ return 0;
+}
+
+static inline void pinconf_free_setting(struct pinctrl_setting const *setting)
+{
+}
+
+static inline int pinconf_apply_setting(struct pinctrl_setting const *setting)
+{
+ return 0;
+}
+
+static inline void pinconf_show_map(struct seq_file *s,
+ struct pinctrl_map const *map)
+{
+}
+
+static inline void pinconf_show_setting(struct seq_file *s,
+ struct pinctrl_setting const *setting)
+{
+}
+
static inline void pinconf_init_device_debugfs(struct dentry *devroot,
struct pinctrl_dev *pctldev)
{
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c
index 359f6ac..0747882 100644
--- a/drivers/pinctrl/pinmux.c
+++ b/drivers/pinctrl/pinmux.c
@@ -58,6 +58,17 @@ int pinmux_check_ops(struct pinctrl_dev *pctldev)
return 0;
}
+int pinmux_validate_map(struct pinctrl_map const *map, int i)
+{
+ if (!map->data.mux.function) {
+ pr_err("failed to register map %s (%d): no function given\n",
+ map->name, i);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
/**
* pin_request() - request a single pin to be muxed in, typically for GPIO
* @pin: the pin number in the global pin space
@@ -284,21 +295,21 @@ int pinmux_map_to_setting(struct pinctrl_map const *map,
const unsigned *pins;
unsigned num_pins;
- setting->func_selector =
- pinmux_func_name_to_selector(pctldev, map->function);
- if (setting->func_selector < 0)
- return setting->func_selector;
+ setting->data.mux.func =
+ pinmux_func_name_to_selector(pctldev, map->data.mux.function);
+ if (setting->data.mux.func < 0)
+ return setting->data.mux.func;
- ret = pmxops->get_function_groups(pctldev, setting->func_selector,
+ ret = pmxops->get_function_groups(pctldev, setting->data.mux.func,
&groups, &num_groups);
if (ret < 0)
return ret;
if (!num_groups)
return -EINVAL;
- if (map->group) {
+ if (map->data.mux.group) {
bool found = false;
- group = map->group;
+ group = map->data.mux.group;
for (i = 0; i < num_groups; i++) {
if (!strcmp(group, groups[i])) {
found = true;
@@ -311,17 +322,16 @@ int pinmux_map_to_setting(struct pinctrl_map const *map,
group = groups[0];
}
- setting->group_selector =
- pinctrl_get_group_selector(pctldev, group);
- if (setting->group_selector < 0)
- return setting->group_selector;
+ setting->data.mux.group = pinctrl_get_group_selector(pctldev, group);
+ if (setting->data.mux.group < 0)
+ return setting->data.mux.group;
- ret = pctlops->get_group_pins(pctldev, setting->group_selector,
- &pins, &num_pins);
+ ret = pctlops->get_group_pins(pctldev, setting->data.mux.group, &pins,
+ &num_pins);
if (ret) {
dev_err(pctldev->dev,
"could not get pins for device %s group selector %d\n",
- pinctrl_dev_get_name(pctldev), setting->group_selector);
+ pinctrl_dev_get_name(pctldev), setting->data.mux.group);
return -ENODEV;
}
@@ -352,12 +362,12 @@ void pinmux_free_setting(struct pinctrl_setting const *setting)
int ret;
int i;
- ret = pctlops->get_group_pins(pctldev, setting->group_selector,
+ ret = pctlops->get_group_pins(pctldev, setting->data.mux.group,
&pins, &num_pins);
if (ret) {
dev_err(pctldev->dev,
"could not get pins for device %s group selector %d\n",
- pinctrl_dev_get_name(pctldev), setting->group_selector);
+ pinctrl_dev_get_name(pctldev), setting->data.mux.group);
return;
}
@@ -370,8 +380,8 @@ int pinmux_enable_setting(struct pinctrl_setting const *setting)
struct pinctrl_dev *pctldev = setting->pctldev;
const struct pinmux_ops *ops = pctldev->desc->pmxops;
- return ops->enable(pctldev, setting->func_selector,
- setting->group_selector);
+ return ops->enable(pctldev, setting->data.mux.func,
+ setting->data.mux.group);
}
void pinmux_disable_setting(struct pinctrl_setting const *setting)
@@ -379,7 +389,7 @@ void pinmux_disable_setting(struct pinctrl_setting const *setting)
struct pinctrl_dev *pctldev = setting->pctldev;
const struct pinmux_ops *ops = pctldev->desc->pmxops;
- ops->disable(pctldev, setting->func_selector, setting->group_selector);
+ ops->disable(pctldev, setting->data.mux.func, setting->data.mux.group);
}
#ifdef CONFIG_DEBUG_FS
@@ -450,18 +460,25 @@ static int pinmux_pins_show(struct seq_file *s, void *what)
return 0;
}
-void pinmux_dbg_show(struct seq_file *s, struct pinctrl_setting const *setting)
+void pinmux_show_map(struct seq_file *s, struct pinctrl_map const *map)
+{
+ seq_printf(s, "group %s\nfunction %s\n",
+ map->data.mux.group ? map->data.mux.group : "(default)",
+ map->data.mux.function);
+}
+
+void pinmux_show_setting(struct seq_file *s,
+ struct pinctrl_setting const *setting)
{
struct pinctrl_dev *pctldev = setting->pctldev;
const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
- seq_printf(s, "controller: %s group: %s (%u) function: %s (%u)\n",
- pinctrl_dev_get_name(pctldev),
- pctlops->get_group_name(pctldev, setting->group_selector),
- setting->group_selector,
- pmxops->get_function_name(pctldev, setting->func_selector),
- setting->func_selector);
+ seq_printf(s, "group: %s (%u) function: %s (%u)\n",
+ pctlops->get_group_name(pctldev, setting->data.mux.group),
+ setting->data.mux.group,
+ pmxops->get_function_name(pctldev, setting->data.mux.func),
+ setting->data.mux.func);
}
static int pinmux_functions_open(struct inode *inode, struct file *file)
diff --git a/drivers/pinctrl/pinmux.h b/drivers/pinctrl/pinmux.h
index 1500ae8..6fc4700 100644
--- a/drivers/pinctrl/pinmux.h
+++ b/drivers/pinctrl/pinmux.h
@@ -14,6 +14,8 @@
int pinmux_check_ops(struct pinctrl_dev *pctldev);
+int pinmux_validate_map(struct pinctrl_map const *map, int i);
+
int pinmux_request_gpio(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned pin, unsigned gpio);
@@ -29,7 +31,9 @@ void pinmux_free_setting(struct pinctrl_setting const *setting);
int pinmux_enable_setting(struct pinctrl_setting const *setting);
void pinmux_disable_setting(struct pinctrl_setting const *setting);
-void pinmux_dbg_show(struct seq_file *s, struct pinctrl_setting const *setting);
+void pinmux_show_map(struct seq_file *s, struct pinctrl_map const *map);
+void pinmux_show_setting(struct seq_file *s,
+ struct pinctrl_setting const *setting);
void pinmux_init_device_debugfs(struct dentry *devroot,
struct pinctrl_dev *pctldev);
@@ -40,6 +44,11 @@ static inline int pinmux_check_ops(struct pinctrl_dev *pctldev)
return 0;
}
+static inline int pinmux_validate_map(struct pinctrl_map const *map, int i)
+{
+ return 0;
+}
+
static inline int pinmux_request_gpio(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned pin, unsigned gpio)
@@ -80,12 +89,18 @@ static inline void pinmux_disable_setting(
{
}
-static inline void pinmux_init_device_debugfs(struct dentry *devroot,
- struct pinctrl_dev *pctldev)
+static inline void pinmux_show_map(struct seq_file *s,
+ struct pinctrl_map const *map)
+{
+}
+
+static inline void pinmux_show_setting(struct seq_file *s,
+ struct pinctrl_setting const *setting)
{
}
-static inline void pinmux_dbg_show(struct seq_file *s, struct pinctrl *p)
+static inline void pinmux_init_device_debugfs(struct dentry *devroot,
+ struct pinctrl_dev *pctldev)
{
}
diff --git a/include/linux/pinctrl/machine.h b/include/linux/pinctrl/machine.h
index e7246dc..1303762 100644
--- a/include/linux/pinctrl/machine.h
+++ b/include/linux/pinctrl/machine.h
@@ -12,6 +12,41 @@
#ifndef __LINUX_PINCTRL_MACHINE_H
#define __LINUX_PINCTRL_MACHINE_H
+enum pinctrl_map_type {
+ PIN_MAP_TYPE_INVALID,
+ PIN_MAP_TYPE_DUMMY_STATE,
+ PIN_MAP_TYPE_MUX_GROUP,
+ PIN_MAP_TYPE_CONFIGS_PIN,
+ PIN_MAP_TYPE_CONFIGS_GROUP,
+};
+
+/**
+ * struct pinctrl_map_mux - mapping table content for MAP_TYPE_MUX_GROUP
+ * @group: the name of the group whose mux function is to be configured. This
+ * field may be left NULL, and the first applicable group for the function
+ * will be used.
+ * @function: the mux function to select for the group
+ */
+struct pinctrl_map_mux {
+ const char *group;
+ const char *function;
+};
+
+/**
+ * struct pinctrl_map_configs - mapping table content for MAP_TYPE_CONFIGS_*
+ * @group_or_pin: the name of the pin or group whose configuration parameters
+ * are to be configured.
+ * @configs: a pointer to an array of config parameters/values to program into
+ * hardware. Each individual pin controller defines the format and meaning
+ * of config parameters.
+ * @num_configs: the number of entries in array @configs
+ */
+struct pinctrl_map_configs {
+ const char *group_or_pin;
+ unsigned long *configs;
+ unsigned num_configs;
+};
+
/**
* struct pinctrl_map - boards/machines shall provide this map for devices
* @dev_name: the name of the device using this specific mapping, the name
@@ -20,45 +55,69 @@
* hogged by the driver itself upon registration
* @name: the name of this specific map entry for the particular machine.
* This is the parameter passed to pinmux_lookup_state()
+ * @type: the type of mapping table entry
* @ctrl_dev_name: the name of the device controlling this specific mapping,
- * the name must be the same as in your struct device*
- * @group: sometimes a function can map to different pin groups, so this
- * selects a certain specific pin group to activate for the function, if
- * left as NULL, the first applicable group will be used
- * @function: a function in the driver to use for this mapping, the driver
- * will lookup the function referenced by this ID on the specified
- * pin control device
+ * the name must be the same as in your struct device*. This field is not
+ * used for PIN_MAP_TYPE_DUMMY_STATE
+ * @data: Data specific to the mapping type
*/
struct pinctrl_map {
const char *dev_name;
const char *name;
+ enum pinctrl_map_type type;
const char *ctrl_dev_name;
- const char *group;
- const char *function;
+ union {
+ struct pinctrl_map_mux mux;
+ struct pinctrl_map_configs configs;
+ } data;
};
-/*
- * Convenience macro to set a simple map from a certain pin controller and a
- * certain function to a named device
- */
-#define PIN_MAP(a, b, c, d) \
- { .name = a, .ctrl_dev_name = b, .function = c, .dev_name = d }
+/* Convenience macros to create mapping table entries */
-/*
- * Convenience macro to map a system function onto a certain pinctrl device,
- * to be hogged by the pin control core until the system shuts down.
- */
-#define PIN_MAP_SYS_HOG(a, b, c) \
- { .name = a, .ctrl_dev_name = b, .dev_name = b, .function = c, }
+#define PIN_MAP_DUMMY_STATE(dev, state) \
+ { \
+ .dev_name = dev, \
+ .name = state, \
+ .type = PIN_MAP_TYPE_DUMMY_STATE, \
+ }
-/*
- * Convenience macro to map a system function onto a certain pinctrl device
- * using a specified group, to be hogged by the pin control core until the
- * system shuts down.
- */
-#define PIN_MAP_SYS_HOG_GROUP(a, b, c, d) \
- { .name = a, .ctrl_dev_name = b, .dev_name = b, .function = c, \
- .group = d, }
+#define PIN_MAP_MUX_GROUP(dev, state, pinctrl, grp, func) \
+ { \
+ .dev_name = dev, \
+ .name = state, \
+ .type = PIN_MAP_TYPE_MUX_GROUP, \
+ .ctrl_dev_name = pinctrl, \
+ .data.mux = { \
+ .group = grp, \
+ .function = func, \
+ }, \
+ }
+
+#define PIN_MAP_MUX_CONFIGS_PIN(dev, state, pinctrl, pin, cfgs) \
+ { \
+ .dev_name = dev, \
+ .name = state, \
+ .type = PIN_MAP_TYPE_CONFIGS_PIN, \
+ .ctrl_dev_name = pinctrl, \
+ .data.configs = { \
+ .group_or_pin = pin, \
+ .configs = cfgs, \
+ .num_configs = ARRAY_SIZE(cfgs), \
+ }, \
+ }
+
+#define PIN_MAP_MUX_CONFIGS_GROUP(dev, state, pinctrl, grp, cfgs) \
+ { \
+ .dev_name = dev, \
+ .name = state, \
+ .type = PIN_MAP_TYPE_CONFIGS_GROUP, \
+ .ctrl_dev_name = pinctrl, \
+ .data.configs = { \
+ .group_or_pin = grp, \
+ .configs = cfgs, \
+ .num_configs = ARRAY_SIZE(cfgs), \
+ }, \
+ }
#ifdef CONFIG_PINMUX
--
1.7.5.4
The API model is changed from:
p = pinctrl_get(dev, "state1");
pinctrl_enable(p);
...
pinctrl_disable(p);
pinctrl_put(p);
p = pinctrl_get(dev, "state2");
pinctrl_enable(p);
...
pinctrl_disable(p);
pinctrl_put(p);
to this:
p = pinctrl_get(dev);
s1 = pinctrl_lookup_state(p, "state1");
s2 = pinctrl_lookup_state(p, "state2");
pinctrl_select_state(p, s1);
...
pinctrl_select_state(p, s2);
...
pinctrl_put(p);
This allows devices to directly transition between states without
disabling the pin controller programming and put()/get()ing the
configuration data each time. This model will also better suit pinconf
programming, which doesn't have a concept of "disable".
The special-case hogging feature of pin controllers is re-written to use
the regular APIs instead of special-case code. Hence, the pinmux-hogs
debugfs file is removed; see the top-level pinctrl-handles files for
equivalent data.
Signed-off-by: Stephen Warren <[email protected]>
---
Documentation/pinctrl.txt | 153 ++++++++-----
arch/arm/mach-u300/core.c | 28 +--
drivers/pinctrl/core.c | 491 +++++++++++++++++--------------------
drivers/pinctrl/core.h | 24 ++-
drivers/tty/serial/sirfsoc_uart.c | 12 +-
include/linux/pinctrl/consumer.h | 55 ++++-
include/linux/pinctrl/machine.h | 21 +-
7 files changed, 408 insertions(+), 376 deletions(-)
diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt
index 12b35db..cacd857 100644
--- a/Documentation/pinctrl.txt
+++ b/Documentation/pinctrl.txt
@@ -781,19 +781,22 @@ spi on the second function mapping:
static const struct pinctrl_map __initdata mapping[] = {
{
+ .dev_name = "foo-spi.0",
+ .name = "default",
.ctrl_dev_name = "pinctrl-foo",
.function = "spi0",
- .dev_name = "foo-spi.0",
},
{
+ .dev_name = "foo-i2c.0",
+ .name = "default",
.ctrl_dev_name = "pinctrl-foo",
.function = "i2c0",
- .dev_name = "foo-i2c.0",
},
{
+ .dev_name = "foo-mmc.0",
+ .name = "default",
.ctrl_dev_name = "pinctrl-foo",
.function = "mmc0",
- .dev_name = "foo-mmc.0",
},
};
@@ -814,7 +817,7 @@ it even more compact which assumes you want to use pinctrl-foo and position
0 for mapping, for example:
static struct pinctrl_map __initdata mapping[] = {
- PIN_MAP("I2CMAP", "pinctrl-foo", "i2c0", "foo-i2c.0"),
+ PIN_MAP("default", "pinctrl-foo", "i2c0", "foo-i2c.0"),
};
@@ -826,81 +829,88 @@ As it is possible to map a function to different groups of pins an optional
...
{
+ .dev_name = "foo-spi.0",
.name = "spi0-pos-A",
.ctrl_dev_name = "pinctrl-foo",
.function = "spi0",
.group = "spi0_0_grp",
- .dev_name = "foo-spi.0",
},
{
+ .dev_name = "foo-spi.0",
.name = "spi0-pos-B",
.ctrl_dev_name = "pinctrl-foo",
.function = "spi0",
.group = "spi0_1_grp",
- .dev_name = "foo-spi.0",
},
...
This example mapping is used to switch between two positions for spi0 at
runtime, as described further below under the heading "Runtime pinmuxing".
-Further it is possible to match several groups of pins to the same function
-for a single device, say for example in the mmc0 example above, where you can
+Further it is possible for one named state to affect the muxing of several
+groups of pins, say for example in the mmc0 example above, where you can
additively expand the mmc0 bus from 2 to 4 to 8 pins. If we want to use all
three groups for a total of 2+2+4 = 8 pins (for an 8-bit MMC bus as is the
case), we define a mapping like this:
...
{
+ .dev_name = "foo-mmc.0",
.name = "2bit"
.ctrl_dev_name = "pinctrl-foo",
.function = "mmc0",
.group = "mmc0_1_grp",
- .dev_name = "foo-mmc.0",
},
{
+ .dev_name = "foo-mmc.0",
.name = "4bit"
.ctrl_dev_name = "pinctrl-foo",
.function = "mmc0",
.group = "mmc0_1_grp",
- .dev_name = "foo-mmc.0",
},
{
+ .dev_name = "foo-mmc.0",
.name = "4bit"
.ctrl_dev_name = "pinctrl-foo",
.function = "mmc0",
.group = "mmc0_2_grp",
- .dev_name = "foo-mmc.0",
},
{
+ .dev_name = "foo-mmc.0",
.name = "8bit"
.ctrl_dev_name = "pinctrl-foo",
+ .function = "mmc0",
.group = "mmc0_1_grp",
- .dev_name = "foo-mmc.0",
},
{
+ .dev_name = "foo-mmc.0",
.name = "8bit"
.ctrl_dev_name = "pinctrl-foo",
.function = "mmc0",
.group = "mmc0_2_grp",
- .dev_name = "foo-mmc.0",
},
{
+ .dev_name = "foo-mmc.0",
.name = "8bit"
.ctrl_dev_name = "pinctrl-foo",
.function = "mmc0",
.group = "mmc0_3_grp",
- .dev_name = "foo-mmc.0",
},
...
The result of grabbing this mapping from the device with something like
this (see next paragraph):
- p = pinctrl_get(&device, "8bit");
+ p = pinctrl_get(dev);
+ s = pinctrl_lookup_state(p, "8bit");
+ ret = pinctrl_select_state(p, s);
+
+or more simply:
+
+ p = pinctrl_get_select(dev, "8bit");
Will be that you activate all the three bottom records in the mapping at
-once. Since they share the same name, pin controller device, funcion and
+once. Since they share the same name, pin controller device, function and
device, and since we allow multiple groups to match to a single device, they
all get selected, and they all get enabled and disable simultaneously by the
pinmux core.
@@ -922,45 +932,63 @@ default state like this:
struct foo_state {
struct pinctrl *p;
+ struct pinctrl_state *s;
...
};
foo_probe()
{
- /* Allocate a state holder named "state" etc */
- struct pinctrl p;
+ /* Allocate a state holder named "foo" etc */
+ struct foo_state *foo = ...;
- p = pinctrl_get(&device, "default");
- if IS_ERR(p)
- return PTR_ERR(p);
- pinctrl_enable(p);
+ foo->p = pinctrl_get(&device);
+ if (IS_ERR(foo->p)) {
+ /* FIXME: clean up "foo" here */
+ return PTR_ERR(foo->p);
+ }
+
+ foo->s = pinctrl_lookup_state(foo->p, "default");
+ if (IS_ERR(foo->s)) {
+ pinctrl_put(foo->p);
+ /* FIXME: clean up "foo" here */
+ return PTR_ERR(s);
+ }
- state->p = p;
+ ret = pinctrl_select_state(s);
+ if (ret < 0) {
+ pinctrl_put(foo->p);
+ /* FIXME: clean up "foo" here */
+ return ret;
+ }
}
foo_remove()
{
- pinctrl_disable(state->p);
pinctrl_put(state->p);
}
-This get/enable/disable/put sequence can just as well be handled by bus drivers
+This get/lookup/select/put sequence can just as well be handled by bus drivers
if you don't want each and every driver to handle it and you know the
arrangement on your bus.
-The semantics of the get/enable respective disable/put is as follows:
+The semantics of the pinctrl APIs are:
+
+- pinctrl_get() is called in process context to obtain a handle to all pinctrl
+ information for a given client device. It will allocate a struct from the
+ kernel memory to hold the pinmux state. All mapping table parsing or similar
+ slow operations take place within this API.
-- pinctrl_get() is called in process context to reserve the pins affected with
- a certain mapping and set up the pinmux core and the driver. It will allocate
- a struct from the kernel memory to hold the pinmux state.
+- pinctrl_lookup_state() is called in process context to obtain a handle to a
+ specific state for a the client device. This operation may be slow too.
-- pinctrl_enable()/pinctrl_disable() is quick and can be called from fastpath
- (irq context) when you quickly want to set up/tear down the hardware muxing
- when running a device driver. Usually it will just poke some values into a
- register.
+- pinctrl_select_state() programs pin controller hardware according to the
+ definition of the state as given by the mapping table. In theory this is a
+ fast-path operation, since it only involved blasting some register settings
+ into hardware. However, note that some pin controllers may have their
+ registers on a slow/IRQ-based bus, so client devices should not assume they
+ can call pinctrl_select_state() from non-blocking contexts.
-- pinctrl_disable() is called in process context to tear down the pin requests
- and release the state holder struct for the mux setting etc.
+- pinctrl_put() frees all information associated with a pinctrl handle.
Usually the pin control core handled the get/put pair and call out to the
device drivers bookkeeping operations, like checking available functions and
@@ -976,25 +1004,25 @@ System pin control hogging
==========================
Pin control map entries can be hogged by the core when the pin controller
-is registered. This means that the core will attempt to call pinctrl_get() and
-pinctrl_enable() on it immediately after the pin control device has been
-registered.
+is registered. This means that the core will attempt to call pinctrl_get(),
+lookup_state() and select_state() on it immediately after the pin control
+device has been registered.
-This is enabled by simply setting the .dev_name field in the map to the name
-of the pin controller itself, like this:
+This occurs for mapping table entries where the client device name is equal
+to the pin controller device name, and the state name is "active".
{
- .name = "POWERMAP"
+ .dev_name = "pinctrl-foo",
+ .name = "active",
.ctrl_dev_name = "pinctrl-foo",
.function = "power_func",
- .dev_name = "pinctrl-foo",
},
Since it may be common to request the core to hog a few always-applicable
mux settings on the primary pin controller, there is a convenience macro for
this:
-PIN_MAP_SYS_HOG("POWERMAP", "pinctrl-foo", "power_func")
+PIN_MAP_SYS_HOG("active", "pinctrl-foo", "power_func")
This gives the exact same result as the above construction.
@@ -1006,8 +1034,8 @@ It is possible to mux a certain function in and out at runtime, say to move
an SPI port from one set of pins to another set of pins. Say for example for
spi0 in the example above, we expose two different groups of pins for the same
function, but with different named in the mapping as described under
-"Advanced mapping" above. So we have two mappings named "spi0-pos-A" and
-"spi0-pos-B".
+"Advanced mapping" above. So that for an SPI device, we have two states named
+"pos-A" and "pos-B".
This snippet first muxes the function in the pins defined by group A, enables
it, disables and releases it, and muxes it in on the pins defined by group B:
@@ -1017,23 +1045,36 @@ it, disables and releases it, and muxes it in on the pins defined by group B:
foo_switch()
{
struct pinctrl *p;
+ struct pinctrl_state *s1, *s2;
+
+ /* Setup */
+ p = pinctrl_get(&device);
+ if (IS_ERR(p))
+ ...
+
+ s1 = pinctrl_lookup_state(foo->p, "pos-A");
+ if (IS_ERR(s1))
+ ...
+
+ s2 = pinctrl_lookup_state(foo->p, "pos-B");
+ if (IS_ERR(s2))
+ ...
/* Enable on position A */
- p = pinctrl_get(&device, "spi0-pos-A");
- if IS_ERR(p)
- return PTR_ERR(p);
- pinctrl_enable(p);
+ ret = pinctrl_select_state(s);
+ if (ret < 0)
+ ...
- /* This releases the pins again */
- pinctrl_disable(p);
- pinctrl_put(p);
+ ...
/* Enable on position B */
- p = pinctrl_get(&device, "spi0-pos-B");
- if IS_ERR(p)
- return PTR_ERR(p);
- pinctrl_enable(p);
+ ret = pinctrl_select_state(s);
+ if (ret < 0)
+ ...
+
...
+
+ pinctrl_put(p);
}
The above has to be done from process context.
diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c
index d66bc97..eb79a49 100644
--- a/arch/arm/mach-u300/core.c
+++ b/arch/arm/mach-u300/core.c
@@ -1554,32 +1554,28 @@ static struct platform_device pinmux_device = {
/* Pinmux settings */
static struct pinctrl_map __initdata u300_pinmux_map[] = {
/* anonymous maps for chip power and EMIFs */
- PIN_MAP_SYS_HOG("POWER", "pinmux-u300", "power"),
- PIN_MAP_SYS_HOG("EMIF0", "pinmux-u300", "emif0"),
- PIN_MAP_SYS_HOG("EMIF1", "pinmux-u300", "emif1"),
+ PIN_MAP_SYS_HOG("default", "pinmux-u300", "power"),
+ PIN_MAP_SYS_HOG("default", "pinmux-u300", "emif0"),
+ PIN_MAP_SYS_HOG("default", "pinmux-u300", "emif1"),
/* per-device maps for MMC/SD, SPI and UART */
- PIN_MAP("MMCSD", "pinmux-u300", "mmc0", "mmci"),
- PIN_MAP("SPI", "pinmux-u300", "spi0", "pl022"),
- PIN_MAP("UART0", "pinmux-u300", "uart0", "uart0"),
+ PIN_MAP("default", "pinmux-u300", "mmc0", "mmci"),
+ PIN_MAP("default", "pinmux-u300", "spi0", "pl022"),
+ PIN_MAP("default", "pinmux-u300", "uart0", "uart0"),
};
struct u300_mux_hog {
- const char *name;
struct device *dev;
struct pinctrl *p;
};
static struct u300_mux_hog u300_mux_hogs[] = {
{
- .name = "uart0",
.dev = &uart0_device.dev,
},
{
- .name = "spi0",
.dev = &pl022_device.dev,
},
{
- .name = "mmc0",
.dev = &mmcsd_device.dev,
},
};
@@ -1592,16 +1588,10 @@ static int __init u300_pinctrl_fetch(void)
struct pinctrl *p;
int ret;
- p = pinctrl_get(u300_mux_hogs[i].dev, NULL);
+ p = pinctrl_get_select_default(u300_mux_hogs[i].dev);
if (IS_ERR(p)) {
- pr_err("u300: could not get pinmux hog %s\n",
- u300_mux_hogs[i].name);
- continue;
- }
- ret = pinctrl_enable(p);
- if (ret) {
- pr_err("u300: could enable pinmux hog %s\n",
- u300_mux_hogs[i].name);
+ pr_err("u300: could not get pinmux hog for dev %s\n",
+ dev_name(u300_mux_hogs[i].dev));
continue;
}
u300_mux_hogs[i].p = p;
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index 2066aee..bab1a69 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -41,18 +41,6 @@ struct pinctrl_maps {
unsigned num_maps;
};
-/**
- * struct pinctrl_hog - a list item to stash control hogs
- * @node: pin control hog list node
- * @map: map entry responsible for this hogging
- * @pmx: the pin control hogged by this item
- */
-struct pinctrl_hog {
- struct list_head node;
- struct pinctrl_map const *map;
- struct pinctrl *p;
-};
-
/* Mutex taken by all entry points */
DEFINE_MUTEX(pinctrl_mutex);
@@ -470,25 +458,98 @@ int pinctrl_gpio_direction_output(unsigned gpio)
}
EXPORT_SYMBOL_GPL(pinctrl_gpio_direction_output);
-static struct pinctrl *pinctrl_get_locked(struct device *dev, const char *name)
+static struct pinctrl_state *find_state(struct pinctrl *p,
+ const char *name)
{
- struct pinctrl_dev *pctldev;
- const char *devname;
- struct pinctrl *p;
- unsigned num_maps = 0;
- int ret;
- struct pinctrl_maps *maps_node;
- int i;
- struct pinctrl_map const *map;
+ struct pinctrl_state *state;
+
+ list_for_each_entry(state, &p->states, node)
+ if (!strcmp(state->name, name))
+ return state;
+
+ return NULL;
+}
+
+static struct pinctrl_state *create_state(struct pinctrl *p,
+ const char *name)
+{
+ struct pinctrl_state *state;
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ if (state == NULL) {
+ dev_err(p->dev,
+ "failed to alloc struct pinctrl_state\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ state->name = name;
+ INIT_LIST_HEAD(&state->settings);
+
+ list_add_tail(&state->node, &p->states);
+
+ return state;
+}
+
+static int add_setting(struct pinctrl *p, struct pinctrl_map const *map)
+{
+ struct pinctrl_state *state;
struct pinctrl_setting *setting;
+ int ret;
- /* We must have both dev and state name */
- if (WARN_ON(!dev || !name))
- return ERR_PTR(-EINVAL);
+ state = find_state(p, map->name);
+ if (!state)
+ state = create_state(p, map->name);
+ if (IS_ERR(state))
+ return PTR_ERR(state);
- devname = dev_name(dev);
+ setting = kzalloc(sizeof(*setting), GFP_KERNEL);
+ if (setting == NULL) {
+ dev_err(p->dev,
+ "failed to alloc struct pinctrl_setting\n");
+ return -ENOMEM;
+ }
+
+ setting->pctldev = get_pinctrl_dev_from_devname(map->ctrl_dev_name);
+ if (setting->pctldev == NULL) {
+ dev_err(p->dev, "unknown pinctrl device %s in map entry",
+ map->ctrl_dev_name);
+ kfree(setting);
+ /* Eventually, this should trigger deferred probe */
+ return -ENODEV;
+ }
+
+ ret = pinmux_map_to_setting(map, setting);
+ if (ret < 0) {
+ kfree(setting);
+ return ret;
+ }
+
+ list_add_tail(&setting->node, &state->settings);
+
+ return 0;
+}
+
+static struct pinctrl *find_pinctrl(struct device *dev)
+{
+ struct pinctrl *p;
- dev_dbg(dev, "pinctrl_get() for state %s\n", name);
+ list_for_each_entry(p, &pinctrldev_list, node)
+ if (p->dev == dev)
+ return p;
+
+ return NULL;
+}
+
+static void pinctrl_put_locked(struct pinctrl *p, bool inlist);
+
+static struct pinctrl *create_pinctrl(struct device *dev)
+{
+ struct pinctrl *p;
+ const char *devname;
+ struct pinctrl_maps *maps_node;
+ int i;
+ struct pinctrl_map const *map;
+ int ret;
/*
* create the state cookie holder struct pinctrl for each
@@ -501,8 +562,9 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev, const char *name)
return ERR_PTR(-ENOMEM);
}
p->dev = dev;
- p->state = name;
- INIT_LIST_HEAD(&p->settings);
+ INIT_LIST_HEAD(&p->states);
+
+ devname = dev_name(dev);
/* Iterate over the pin control maps to locate the right ones */
for_each_maps(maps_node, i, map) {
@@ -510,181 +572,183 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev, const char *name)
if (strcmp(map->dev_name, devname))
continue;
- /* State name must be the one we're looking for */
- if (strcmp(map->name, name))
- continue;
-
- /*
- * First, try to find the pctldev given in the map
- */
- pctldev = get_pinctrl_dev_from_devname(map->ctrl_dev_name);
- if (!pctldev) {
- dev_err(dev, "unknown pinctrl device %s in map entry",
- map->ctrl_dev_name);
- /* Eventually, this should trigger deferred probe */
- ret = -ENODEV;
- goto error;
- }
-
- dev_dbg(dev, "in map, found pctldev %s to handle function %s",
- dev_name(pctldev->dev), map->function);
-
- setting = kzalloc(sizeof(*setting), GFP_KERNEL);
- if (setting == NULL) {
- dev_err(dev,
- "failed to alloc struct pinctrl_setting\n");
- ret = -ENOMEM;
- goto error;
+ ret = add_setting(p, map);
+ if (ret < 0) {
+ pinctrl_put_locked(p, false);
+ return ERR_PTR(ret);
}
-
- setting->pctldev = pctldev;
- ret = pinmux_map_to_setting(map, setting);
- if (ret < 0)
- goto error;
-
- list_add_tail(&setting->node, &p->settings);
- num_maps++;
}
- /*
- * This may be perfectly legitimate. An IP block may get re-used
- * across SoCs. Not all of those SoCs may need pinmux settings for the
- * IP block, e.g. if one SoC dedicates pins to that function but
- * another doesn't. The driver won't know this, and will always
- * attempt to set up the pinmux. The mapping table defines whether any
- * HW programming is actually needed.
- */
- if (!num_maps)
- dev_info(dev, "zero maps found for state %s\n", name);
-
- dev_dbg(dev, "found %u maps for state %s\n", num_maps, name);
-
/* Add the pinmux to the global list */
list_add_tail(&p->node, &pinctrl_list);
return p;
+}
+
+static struct pinctrl *pinctrl_get_locked(struct device *dev)
+{
+ struct pinctrl *p;
-error:
- list_for_each_entry(setting, &p->settings, node)
- pinmux_free_setting(setting);
+ if (WARN_ON(!dev))
+ return ERR_PTR(-EINVAL);
- kfree(p);
+ p = find_pinctrl(dev);
+ if (p == NULL)
+ p = create_pinctrl(dev);
+ if (IS_ERR(p))
+ return p;
+
+ p->usecount++;
- return ERR_PTR(ret);
+ return p;
}
/**
- * pinctrl_get() - retrieves the pin controller handle for a certain device
- * @dev: the device to get the pin controller handle for
- * @name: an optional specific control mapping name or NULL, the name is only
- * needed if you want to have more than one mapping per device, or if you
- * need an anonymous pin control (not tied to any specific device)
+ * pinctrl_get() - retrieves the pinctrl handle for a device
+ * @dev: the device to obtain the handle for
*/
-struct pinctrl *pinctrl_get(struct device *dev, const char *name)
+struct pinctrl *pinctrl_get(struct device *dev)
{
struct pinctrl *p;
mutex_lock(&pinctrl_mutex);
- p = pinctrl_get_locked(dev, name);
+ p = pinctrl_get_locked(dev);
mutex_unlock(&pinctrl_mutex);
return p;
}
EXPORT_SYMBOL_GPL(pinctrl_get);
-static void pinctrl_put_locked(struct pinctrl *p)
+static void pinctrl_put_locked(struct pinctrl *p, bool inlist)
{
- struct pinctrl_setting *setting, *n;
+ struct pinctrl_state *state, *n1;
+ struct pinctrl_setting *setting, *n2;
- if (p == NULL)
+ p->usecount--;
+ if (p->usecount)
return;
- if (p->usecount)
- pr_warn("releasing pin control handle with active users!\n");
- list_for_each_entry_safe(setting, n, &p->settings, node) {
- pinmux_free_setting(setting);
- list_del(&setting->node);
- kfree(setting);
+ list_for_each_entry_safe(state, n1, &p->states, node) {
+ list_for_each_entry_safe(setting, n2, &state->settings, node) {
+ if (state == p->state)
+ pinmux_disable_setting(setting);
+ pinmux_free_setting(setting);
+ list_del(&setting->node);
+ kfree(setting);
+ }
+ list_del(&state->node);
+ kfree(state);
}
- /* Remove from list */
- list_del(&p->node);
-
+ if (inlist)
+ list_del(&p->node);
kfree(p);
}
/**
- * pinctrl_put() - release a previously claimed pin control handle
- * @p: a pin control handle previously claimed by pinctrl_get()
+ * pinctrl_put() - release a previously claimed pinctrl handle
+ * @p: the pinctrl handle to release
*/
void pinctrl_put(struct pinctrl *p)
{
mutex_lock(&pinctrl_mutex);
- pinctrl_put(p);
+ pinctrl_put_locked(p, true);
mutex_unlock(&pinctrl_mutex);
}
EXPORT_SYMBOL_GPL(pinctrl_put);
-static int pinctrl_enable_locked(struct pinctrl *p)
+static struct pinctrl_state *pinctrl_lookup_state_locked(struct pinctrl *p,
+ const char *name)
{
- struct pinctrl_setting *setting;
- int ret;
+ struct pinctrl_state *state;
- if (p == NULL)
- return -EINVAL;
+ state = find_state(p, name);
+ if (!state)
+ return ERR_PTR(-ENODEV);
- if (p->usecount++ == 0) {
- list_for_each_entry(setting, &p->settings, node) {
- ret = pinmux_enable_setting(setting);
- if (ret < 0) {
- /* FIXME: Difficult to return to prev state */
- p->usecount--;
- return ret;
- }
- }
- }
-
- return 0;
+ return state;
}
/**
- * pinctrl_enable() - enable a certain pin controller setting
- * @p: the pin control handle to enable, previously claimed by pinctrl_get()
+ * pinctrl_lookup_state() - retrieves a state handle from a pinctrl handle
+ * @p: the pinctrl handle to retrieve the state from
+ * @name: the state name to retrieve
*/
-int pinctrl_enable(struct pinctrl *p)
+struct pinctrl_state *pinctrl_lookup_state(struct pinctrl *p, const char *name)
{
- int ret;
+ struct pinctrl_state *s;
+
mutex_lock(&pinctrl_mutex);
- ret = pinctrl_enable_locked(p);
+ s = pinctrl_lookup_state_locked(p, name);
mutex_unlock(&pinctrl_mutex);
- return ret;
+
+ return s;
}
-EXPORT_SYMBOL_GPL(pinctrl_enable);
+EXPORT_SYMBOL_GPL(pinctrl_lookup_state);
-static void pinctrl_disable_locked(struct pinctrl *p)
+static int pinctrl_select_state_locked(struct pinctrl *p,
+ struct pinctrl_state *state)
{
- struct pinctrl_setting *setting;
+ struct pinctrl_setting *setting, *setting2;
+ int ret;
- if (p == NULL)
- return;
+ if (p->state == state)
+ return 0;
+
+ if (p->state) {
+ /*
+ * The set of groups with a mux configuration in the old state
+ * may not be identical to the set of groups with a mux setting
+ * in the new state. While this might be unusual, it's entirely
+ * possible for the "user"-supplied mapping table to be written
+ * that way. For each group that was configured in the old state
+ * but not in the new state, this code puts that group into a
+ * safe/disabled state.
+ */
+ list_for_each_entry(setting, &p->state->settings, node) {
+ bool found = false;
+ list_for_each_entry(setting2, &state->settings, node) {
+ if (setting2->group_selector ==
+ setting->group_selector) {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ pinmux_disable_setting(setting);
+ }
+ }
+
+ p->state = state;
- if (--p->usecount == 0) {
- list_for_each_entry(setting, &p->settings, node)
- pinmux_disable_setting(setting);
+ /* Apply all the settings for the new state */
+ list_for_each_entry(setting, &state->settings, node) {
+ ret = pinmux_enable_setting(setting);
+ if (ret < 0) {
+ /* FIXME: Difficult to return to prev state */
+ return ret;
+ }
}
+
+ return 0;
}
/**
- * pinctrl_disable() - disable a certain pin control setting
- * @p: the pin control handle to disable, previously claimed by pinctrl_get()
+ * pinctrl_select() - select/activate/program a pinctrl state to HW
+ * @p: the pinctrl handle for the device that requests configuratio
+ * @state: the state handle to select/activate/program
*/
-void pinctrl_disable(struct pinctrl *p)
+int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state)
{
+ int ret;
+
mutex_lock(&pinctrl_mutex);
- pinctrl_disable_locked(p);
+ ret = pinctrl_select_state_locked(p, state);
mutex_unlock(&pinctrl_mutex);
+
+ return ret;
}
-EXPORT_SYMBOL_GPL(pinctrl_disable);
+EXPORT_SYMBOL_GPL(pinctrl_select_state);
/**
* pinctrl_register_mappings() - register a set of pin controller mappings
@@ -749,99 +813,6 @@ int pinctrl_register_mappings(struct pinctrl_map const *maps,
return 0;
}
-/* Hog a single map entry and add to the hoglist */
-static int pinctrl_hog_map(struct pinctrl_dev *pctldev,
- struct pinctrl_map const *map)
-{
- struct pinctrl_hog *hog;
- struct pinctrl *p;
- int ret;
-
- hog = kzalloc(sizeof(*hog), GFP_KERNEL);
- if (!hog) {
- dev_err(pctldev->dev, "failed to alloc struct pinctrl_hog\n");
- return -ENOMEM;
- }
-
- p = pinctrl_get_locked(pctldev->dev, map->name);
- if (IS_ERR(p)) {
- kfree(hog);
- dev_err(pctldev->dev,
- "could not get the %s pin control mapping for hogging\n",
- map->name);
- return PTR_ERR(p);
- }
-
- ret = pinctrl_enable_locked(p);
- if (ret) {
- pinctrl_put_locked(p);
- kfree(hog);
- dev_err(pctldev->dev,
- "could not enable the %s pin control mapping for hogging\n",
- map->name);
- return ret;
- }
-
- hog->map = map;
- hog->p = p;
-
- dev_info(pctldev->dev, "hogged map %s, function %s\n", map->name,
- map->function);
- list_add_tail(&hog->node, &pctldev->pinctrl_hogs);
-
- return 0;
-}
-
-/**
- * pinctrl_hog_maps() - hog specific map entries on controller device
- * @pctldev: the pin control device to hog entries on
- *
- * When the pin controllers are registered, there may be some specific pinmux
- * map entries that need to be hogged, i.e. get+enabled until the system shuts
- * down.
- */
-static int pinctrl_hog_maps(struct pinctrl_dev *pctldev)
-{
- struct device *dev = pctldev->dev;
- const char *devname = dev_name(dev);
- int ret;
- struct pinctrl_maps *maps_node;
- int i;
- struct pinctrl_map const *map;
-
- INIT_LIST_HEAD(&pctldev->pinctrl_hogs);
-
- for_each_maps(maps_node, i, map) {
- if (!strcmp(map->ctrl_dev_name, devname) &&
- !strcmp(map->dev_name, devname)) {
- /* OK time to hog! */
- ret = pinctrl_hog_map(pctldev, map);
- if (ret)
- return ret;
- }
- }
-
- return 0;
-}
-
-/**
- * pinctrl_unhog_maps() - unhog specific map entries on controller device
- * @pctldev: the pin control device to unhog entries on
- */
-static void pinctrl_unhog_maps(struct pinctrl_dev *pctldev)
-{
- struct list_head *node, *tmp;
-
- list_for_each_safe(node, tmp, &pctldev->pinctrl_hogs) {
- struct pinctrl_hog *hog =
- list_entry(node, struct pinctrl_hog, node);
- pinctrl_disable_locked(hog->p);
- pinctrl_put_locked(hog->p);
- list_del(node);
- kfree(hog);
- }
-}
-
#ifdef CONFIG_DEBUG_FS
static int pinctrl_pins_show(struct seq_file *s, void *what)
@@ -965,23 +936,6 @@ static int pinctrl_maps_show(struct seq_file *s, void *what)
return 0;
}
-static int pinmux_hogs_show(struct seq_file *s, void *what)
-{
- struct pinctrl_dev *pctldev = s->private;
- struct pinctrl_hog *hog;
-
- seq_puts(s, "Pin control map hogs held by device\n");
-
- mutex_lock(&pinctrl_mutex);
-
- list_for_each_entry(hog, &pctldev->pinctrl_hogs, node)
- seq_printf(s, "%s\n", hog->map->name);
-
- mutex_unlock(&pinctrl_mutex);
-
- return 0;
-}
-
static int pinctrl_devices_show(struct seq_file *s, void *what)
{
struct pinctrl_dev *pctldev;
@@ -1011,6 +965,7 @@ static int pinctrl_devices_show(struct seq_file *s, void *what)
static int pinctrl_show(struct seq_file *s, void *what)
{
struct pinctrl *p;
+ struct pinctrl_state *state;
struct pinctrl_setting *setting;
seq_puts(s, "Requested pin control handlers their pinmux maps:\n");
@@ -1018,12 +973,17 @@ static int pinctrl_show(struct seq_file *s, void *what)
mutex_lock(&pinctrl_mutex);
list_for_each_entry(p, &pinctrl_list, node) {
- seq_printf(s, "device: %s state: %s users: %u\n",
- dev_name(p->dev), p->state, p->usecount);
+ seq_printf(s, "device: %s current state: %s users: %u\n",
+ dev_name(p->dev),
+ p->state ? p->state->name : "none", p->usecount);
+
+ list_for_each_entry(state, &p->states, node) {
+ seq_printf(s, " state: %s\n", state->name);
- list_for_each_entry(setting, &p->settings, node) {
- seq_printf(s, " ");
- pinmux_dbg_show(s, setting);
+ list_for_each_entry(setting, &state->settings, node) {
+ seq_printf(s, " ");
+ pinmux_dbg_show(s, setting);
+ }
}
}
@@ -1052,11 +1012,6 @@ static int pinctrl_maps_open(struct inode *inode, struct file *file)
return single_open(file, pinctrl_maps_show, inode->i_private);
}
-static int pinmux_hogs_open(struct inode *inode, struct file *file)
-{
- return single_open(file, pinmux_hogs_show, inode->i_private);
-}
-
static int pinctrl_devices_open(struct inode *inode, struct file *file)
{
return single_open(file, pinctrl_devices_show, NULL);
@@ -1095,13 +1050,6 @@ static const struct file_operations pinctrl_maps_ops = {
.release = single_release,
};
-static const struct file_operations pinmux_hogs_ops = {
- .open = pinmux_hogs_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
static const struct file_operations pinctrl_devices_ops = {
.open = pinctrl_devices_open,
.read = seq_read,
@@ -1139,8 +1087,6 @@ static void pinctrl_init_device_debugfs(struct pinctrl_dev *pctldev)
device_root, pctldev, &pinctrl_gpioranges_ops);
debugfs_create_file("pinctrl-maps", S_IFREG | S_IRUGO,
device_root, pctldev, &pinctrl_maps_ops);
- debugfs_create_file("pinmux-hogs", S_IFREG | S_IRUGO,
- device_root, pctldev, &pinmux_hogs_ops);
pinmux_init_device_debugfs(device_root, pctldev);
pinconf_init_device_debugfs(device_root, pctldev);
}
@@ -1248,7 +1194,14 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
mutex_lock(&pinctrl_mutex);
list_add_tail(&pctldev->node, &pinctrldev_list);
- pinctrl_hog_maps(pctldev);
+
+ pctldev->p = pinctrl_get_locked(pctldev->dev);
+ if (!IS_ERR(pctldev->p)) {
+ struct pinctrl_state *s =
+ pinctrl_lookup_state_locked(pctldev->p, "active");
+ if (!IS_ERR(s))
+ pinctrl_select_state_locked(pctldev->p, s);
+ }
mutex_unlock(&pinctrl_mutex);
@@ -1275,7 +1228,9 @@ void pinctrl_unregister(struct pinctrl_dev *pctldev)
mutex_lock(&pinctrl_mutex);
- pinctrl_unhog_maps(pctldev);
+ if (!IS_ERR(pctldev->p))
+ pinctrl_put_locked(pctldev->p, true);
+
/* TODO: check that no pinmuxes are still active? */
list_del(&pctldev->node);
/* Destroy descriptor tree */
diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h
index 64ae1b8..d5bc9ea 100644
--- a/drivers/pinctrl/core.h
+++ b/drivers/pinctrl/core.h
@@ -28,7 +28,7 @@ struct pinctrl_gpio_range;
* @owner: module providing the pin controller, used for refcounting
* @driver_data: driver data for drivers registering to the pin controller
* subsystem
- * @pinctrl_hogs: list of pin control maps hogged by this device
+ * @p: result of pinctrl_get() for this device
* @device_root: debugfs root for this device
*/
struct pinctrl_dev {
@@ -39,7 +39,7 @@ struct pinctrl_dev {
struct device *dev;
struct module *owner;
void *driver_data;
- struct list_head pinctrl_hogs;
+ struct pinctrl *p;
#ifdef CONFIG_DEBUG_FS
struct dentry *device_root;
#endif
@@ -49,22 +49,34 @@ struct pinctrl_dev {
* struct pinctrl - per-device pin control state holder
* @node: global list node
* @dev: the device using this pin control handle
- * @state: the state name passed to pinctrl_get()
* @usecount: the number of active users of this pin controller setting, used
* to keep track of nested use cases
- * @settings: a list of settings for this device/state
+ * @states: a list of states for this device
+ * @state: the current state
*/
struct pinctrl {
struct list_head node;
struct device *dev;
- const char *state;
unsigned usecount;
+ struct list_head states;
+ struct pinctrl_state *state;
+};
+
+/**
+ * struct pinctrl_state - a pinctrl state for a device
+ * @node: list not for struct pinctrl's @states field
+ * @name: the name of this state
+ * @settings: a list of settings for this state
+ */
+struct pinctrl_state {
+ struct list_head node;
+ const char *name;
struct list_head settings;
};
/**
* struct pinctrl_setting - an individual mux setting
- * @node: list node for struct pinctrl's @settings field
+ * @node: list node for struct pinctrl_settings's @settings field
* @pctldev: pin control device handling to be programmed
* @group_selector: the group selector to program
* @func_selector: the function selector to program
diff --git a/drivers/tty/serial/sirfsoc_uart.c b/drivers/tty/serial/sirfsoc_uart.c
index c1a871e..5b3eda2 100644
--- a/drivers/tty/serial/sirfsoc_uart.c
+++ b/drivers/tty/serial/sirfsoc_uart.c
@@ -673,12 +673,10 @@ int sirfsoc_uart_probe(struct platform_device *pdev)
port->irq = res->start;
if (sirfport->hw_flow_ctrl) {
- sirfport->p = pinctrl_get(&pdev->dev, NULL);
+ sirfport->p = pinctrl_get_select_default(&pdev->dev);
ret = IS_ERR(sirfport->p);
if (ret)
goto pin_err;
-
- pinctrl_enable(sirfport->p);
}
port->ops = &sirfsoc_uart_ops;
@@ -695,10 +693,8 @@ int sirfsoc_uart_probe(struct platform_device *pdev)
port_err:
platform_set_drvdata(pdev, NULL);
- if (sirfport->hw_flow_ctrl) {
- pinctrl_disable(sirfport->p);
+ if (sirfport->hw_flow_ctrl)
pinctrl_put(sirfport->p);
- }
pin_err:
irq_err:
devm_iounmap(&pdev->dev, port->membase);
@@ -711,10 +707,8 @@ static int sirfsoc_uart_remove(struct platform_device *pdev)
struct sirfsoc_uart_port *sirfport = platform_get_drvdata(pdev);
struct uart_port *port = &sirfport->port;
platform_set_drvdata(pdev, NULL);
- if (sirfport->hw_flow_ctrl) {
- pinctrl_disable(sirfport->p);
+ if (sirfport->hw_flow_ctrl)
pinctrl_put(sirfport->p);
- }
devm_iounmap(&pdev->dev, port->membase);
uart_remove_one_port(&sirfsoc_uart_drv, port);
return 0;
diff --git a/include/linux/pinctrl/consumer.h b/include/linux/pinctrl/consumer.h
index 3086594..a520c46 100644
--- a/include/linux/pinctrl/consumer.h
+++ b/include/linux/pinctrl/consumer.h
@@ -12,12 +12,14 @@
#ifndef __LINUX_PINCTRL_CONSUMER_H
#define __LINUX_PINCTRL_CONSUMER_H
+#include <linux/err.h>
#include <linux/list.h>
#include <linux/seq_file.h>
#include "pinctrl.h"
/* This struct is private to the core and should be regarded as a cookie */
struct pinctrl;
+struct pinctrl_state;
#ifdef CONFIG_PINCTRL
@@ -26,10 +28,13 @@ extern int pinctrl_request_gpio(unsigned gpio);
extern void pinctrl_free_gpio(unsigned gpio);
extern int pinctrl_gpio_direction_input(unsigned gpio);
extern int pinctrl_gpio_direction_output(unsigned gpio);
-extern struct pinctrl * __must_check pinctrl_get(struct device *dev, const char *name);
+
+extern struct pinctrl * __must_check pinctrl_get(struct device *dev);
extern void pinctrl_put(struct pinctrl *p);
-extern int pinctrl_enable(struct pinctrl *p);
-extern void pinctrl_disable(struct pinctrl *p);
+extern struct pinctrl_state * __must_check pinctrl_lookup_state(
+ struct pinctrl *p,
+ const char *name);
+extern int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *s);
#else /* !CONFIG_PINCTRL */
@@ -52,7 +57,7 @@ static inline int pinctrl_gpio_direction_output(unsigned gpio)
return 0;
}
-static inline struct pinctrl * __must_check pinctrl_get(struct device *dev, const char *name)
+static inline struct pinctrl * __must_check pinctrl_get(struct device *dev)
{
return NULL;
}
@@ -61,17 +66,53 @@ static inline void pinctrl_put(struct pinctrl *p)
{
}
-static inline int pinctrl_enable(struct pinctrl *p)
+static inline struct pinctrl_state * __must_check pinctrl_lookup_state(
+ struct pinctrl *p,
+ const char *name)
{
- return 0;
+ return NULL;
}
-static inline void pinctrl_disable(struct pinctrl *p)
+static inline int pinctrl_select_state(struct pinctrl *p,
+ struct pinctrl_state *s)
{
+ return 0;
}
#endif /* CONFIG_PINCTRL */
+static inline struct pinctrl * __must_check pinctrl_get_select(
+ struct device *dev, const char *name)
+{
+ struct pinctrl *p;
+ struct pinctrl_state *s;
+ int ret;
+
+ p = pinctrl_get(dev);
+ if (IS_ERR(p))
+ return p;
+
+ s = pinctrl_lookup_state(p, name);
+ if (IS_ERR(s)) {
+ pinctrl_put(p);
+ return ERR_PTR(PTR_ERR(s));
+ }
+
+ ret = pinctrl_select_state(p, s);
+ if (ret < 0) {
+ pinctrl_put(p);
+ return ERR_PTR(ret);
+ }
+
+ return p;
+}
+
+static inline struct pinctrl * __must_check pinctrl_get_select_default(
+ struct device *dev)
+{
+ return pinctrl_get_select(dev, "default");
+}
+
#ifdef CONFIG_PINCONF
extern int pin_config_get(const char *dev_name, const char *name,
diff --git a/include/linux/pinctrl/machine.h b/include/linux/pinctrl/machine.h
index 400f192..e7246dc 100644
--- a/include/linux/pinctrl/machine.h
+++ b/include/linux/pinctrl/machine.h
@@ -14,28 +14,27 @@
/**
* struct pinctrl_map - boards/machines shall provide this map for devices
+ * @dev_name: the name of the device using this specific mapping, the name
+ * must be the same as in your struct device*. If this name is set to the
+ * same name as the pin controllers own dev_name(), the map entry will be
+ * hogged by the driver itself upon registration
* @name: the name of this specific map entry for the particular machine.
- * This is the second parameter passed to pinmux_get() when you want
- * to have several mappings to the same device
+ * This is the parameter passed to pinmux_lookup_state()
* @ctrl_dev_name: the name of the device controlling this specific mapping,
* the name must be the same as in your struct device*
- * @function: a function in the driver to use for this mapping, the driver
- * will lookup the function referenced by this ID on the specified
- * pin control device
* @group: sometimes a function can map to different pin groups, so this
* selects a certain specific pin group to activate for the function, if
* left as NULL, the first applicable group will be used
- * @dev_name: the name of the device using this specific mapping, the name
- * must be the same as in your struct device*. If this name is set to the
- * same name as the pin controllers own dev_name(), the map entry will be
- * hogged by the driver itself upon registration
+ * @function: a function in the driver to use for this mapping, the driver
+ * will lookup the function referenced by this ID on the specified
+ * pin control device
*/
struct pinctrl_map {
+ const char *dev_name;
const char *name;
const char *ctrl_dev_name;
- const char *function;
const char *group;
- const char *dev_name;
+ const char *function;
};
/*
--
1.7.5.4
This change separates two aspects of struct pinctrl:
a) The data representation of the parsed mapping table, into:
1) The top-level struct pinctrl object, a single entity returned
by pinctrl_get().
2) The parsed version of each mapping table entry, struct
pinctrl_setting, of which there is one per mapping table entry.
b) The code that handles this; the code for (1) above is in core.c, and
the code to parse/execute each entry in (2) above is in pinmux.c, while
the iteration over multiple settings is lifted to core.c.
This will allow the following future changes:
1) pinctrl_get() API rework, so that struct pinctrl represents all states
for the device, and the device can select between them without calling
put()/get() again.
2) To support that, a struct pinctrl_state object will be inserted into
the data model between the struct pinctrl and struct pinctrl_setting.
3) The mapping table will be extended to allow specification of pin config
settings too. To support this, struct pinctrl_setting will be enhanced
to store either mux settings or config settings, and functions will be
added to pinconf.c to parse/execute pin configuration settings.
Signed-off-by: Stephen Warren <[email protected]>
---
drivers/pinctrl/core.c | 103 +++++++-----
drivers/pinctrl/core.h | 26 ++-
drivers/pinctrl/pinmux.c | 409 +++++++++++-----------------------------------
drivers/pinctrl/pinmux.h | 42 ++---
4 files changed, 193 insertions(+), 387 deletions(-)
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index 7cb64e6..2066aee 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -472,14 +472,15 @@ EXPORT_SYMBOL_GPL(pinctrl_gpio_direction_output);
static struct pinctrl *pinctrl_get_locked(struct device *dev, const char *name)
{
- struct pinctrl_dev *pctldev = NULL;
+ struct pinctrl_dev *pctldev;
const char *devname;
struct pinctrl *p;
unsigned num_maps = 0;
- int ret = -ENODEV;
+ int ret;
struct pinctrl_maps *maps_node;
int i;
struct pinctrl_map const *map;
+ struct pinctrl_setting *setting;
/* We must have both dev and state name */
if (WARN_ON(!dev || !name))
@@ -499,10 +500,20 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev, const char *name)
dev_err(dev, "failed to alloc struct pinctrl\n");
return ERR_PTR(-ENOMEM);
}
- pinmux_init_pinctrl_handle(p);
+ p->dev = dev;
+ p->state = name;
+ INIT_LIST_HEAD(&p->settings);
/* Iterate over the pin control maps to locate the right ones */
for_each_maps(maps_node, i, map) {
+ /* Map must be for this device */
+ if (strcmp(map->dev_name, devname))
+ continue;
+
+ /* State name must be the one we're looking for */
+ if (strcmp(map->name, name))
+ continue;
+
/*
* First, try to find the pctldev given in the map
*/
@@ -510,29 +521,28 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev, const char *name)
if (!pctldev) {
dev_err(dev, "unknown pinctrl device %s in map entry",
map->ctrl_dev_name);
- pinmux_put(p);
- kfree(p);
/* Eventually, this should trigger deferred probe */
- return ERR_PTR(-ENODEV);
+ ret = -ENODEV;
+ goto error;
}
dev_dbg(dev, "in map, found pctldev %s to handle function %s",
dev_name(pctldev->dev), map->function);
- /* Map must be for this device */
- if (strcmp(map->dev_name, devname))
- continue;
+ setting = kzalloc(sizeof(*setting), GFP_KERNEL);
+ if (setting == NULL) {
+ dev_err(dev,
+ "failed to alloc struct pinctrl_setting\n");
+ ret = -ENOMEM;
+ goto error;
+ }
- /* State name must be the one we're looking for */
- if (strcmp(map->name, name))
- continue;
+ setting->pctldev = pctldev;
+ ret = pinmux_map_to_setting(map, setting);
+ if (ret < 0)
+ goto error;
- ret = pinmux_apply_muxmap(pctldev, p, dev,
- devname, map);
- if (ret) {
- kfree(p);
- return ERR_PTR(ret);
- }
+ list_add_tail(&setting->node, &p->settings);
num_maps++;
}
@@ -553,6 +563,14 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev, const char *name)
list_add_tail(&p->node, &pinctrl_list);
return p;
+
+error:
+ list_for_each_entry(setting, &p->settings, node)
+ pinmux_free_setting(setting);
+
+ kfree(p);
+
+ return ERR_PTR(ret);
}
/**
@@ -576,13 +594,18 @@ EXPORT_SYMBOL_GPL(pinctrl_get);
static void pinctrl_put_locked(struct pinctrl *p)
{
+ struct pinctrl_setting *setting, *n;
+
if (p == NULL)
return;
if (p->usecount)
pr_warn("releasing pin control handle with active users!\n");
- /* Free the groups and all acquired pins */
- pinmux_put(p);
+ list_for_each_entry_safe(setting, n, &p->settings, node) {
+ pinmux_free_setting(setting);
+ list_del(&setting->node);
+ kfree(setting);
+ }
/* Remove from list */
list_del(&p->node);
@@ -604,18 +627,24 @@ EXPORT_SYMBOL_GPL(pinctrl_put);
static int pinctrl_enable_locked(struct pinctrl *p)
{
- int ret = 0;
+ struct pinctrl_setting *setting;
+ int ret;
if (p == NULL)
return -EINVAL;
if (p->usecount++ == 0) {
- ret = pinmux_enable(p);
- if (ret)
- p->usecount--;
+ list_for_each_entry(setting, &p->settings, node) {
+ ret = pinmux_enable_setting(setting);
+ if (ret < 0) {
+ /* FIXME: Difficult to return to prev state */
+ p->usecount--;
+ return ret;
+ }
+ }
}
- return ret;
+ return 0;
}
/**
@@ -634,11 +663,14 @@ EXPORT_SYMBOL_GPL(pinctrl_enable);
static void pinctrl_disable_locked(struct pinctrl *p)
{
+ struct pinctrl_setting *setting;
+
if (p == NULL)
return;
if (--p->usecount == 0) {
- pinmux_disable(p);
+ list_for_each_entry(setting, &p->settings, node)
+ pinmux_disable_setting(setting);
}
}
@@ -979,27 +1011,20 @@ static int pinctrl_devices_show(struct seq_file *s, void *what)
static int pinctrl_show(struct seq_file *s, void *what)
{
struct pinctrl *p;
+ struct pinctrl_setting *setting;
seq_puts(s, "Requested pin control handlers their pinmux maps:\n");
mutex_lock(&pinctrl_mutex);
list_for_each_entry(p, &pinctrl_list, node) {
- struct pinctrl_dev *pctldev = p->pctldev;
+ seq_printf(s, "device: %s state: %s users: %u\n",
+ dev_name(p->dev), p->state, p->usecount);
- if (!pctldev) {
- seq_puts(s, "NO PIN CONTROLLER DEVICE\n");
- continue;
+ list_for_each_entry(setting, &p->settings, node) {
+ seq_printf(s, " ");
+ pinmux_dbg_show(s, setting);
}
-
- seq_printf(s, "device: %s",
- pinctrl_dev_get_name(p->pctldev));
-
- pinmux_dbg_show(s, p);
-
- seq_printf(s, " users: %u map-> %s\n",
- p->usecount,
- p->dev ? dev_name(p->dev) : "(system)");
}
mutex_unlock(&pinctrl_mutex);
diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h
index 4cdc38d..1290995 100644
--- a/drivers/pinctrl/core.h
+++ b/drivers/pinctrl/core.h
@@ -49,25 +49,31 @@ struct pinctrl_dev {
* struct pinctrl - per-device pin control state holder
* @node: global list node
* @dev: the device using this pin control handle
+ * @state: the state name passed to pinctrl_get()
* @usecount: the number of active users of this pin controller setting, used
* to keep track of nested use cases
- * @pctldev: pin control device handling this pin control handle
- * @func_selector: the function selector for the pinmux device handling
- * this pinmux
- * @groups: the group selectors for the pinmux device and
- * selector combination handling this pinmux, this is a list that
- * will be traversed on all pinmux operations such as
- * get/put/enable/disable
+ * @settings: a list of settings for this device/state
*/
struct pinctrl {
struct list_head node;
struct device *dev;
+ const char *state;
unsigned usecount;
+ struct list_head settings;
+};
+
+/**
+ * struct pinctrl_setting - an individual mux setting
+ * @node: list node for struct pinctrl's @settings field
+ * @pctldev: pin control device handling to be programmed
+ * @group_selector: the group selector to program
+ * @func_selector: the function selector to program
+ */
+struct pinctrl_setting {
+ struct list_head node;
struct pinctrl_dev *pctldev;
-#ifdef CONFIG_PINMUX
+ unsigned group_selector;
unsigned func_selector;
- struct list_head groups;
-#endif
};
/**
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c
index c574751..8d32380 100644
--- a/drivers/pinctrl/pinmux.c
+++ b/drivers/pinctrl/pinmux.c
@@ -7,6 +7,8 @@
*
* Author: Linus Walleij <[email protected]>
*
+ * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
+ *
* License terms: GNU General Public License (GPL) version 2
*/
#define pr_fmt(fmt) "pinmux core: " fmt
@@ -28,16 +30,6 @@
#include "core.h"
#include "pinmux.h"
-/**
- * struct pinmux_group - group list item for pinmux groups
- * @node: pinmux group list node
- * @group_selector: the group selector for this group
- */
-struct pinmux_group {
- struct list_head node;
- unsigned group_selector;
-};
-
int pinmux_check_ops(struct pinctrl_dev *pctldev)
{
const struct pinmux_ops *ops = pctldev->desc->pmxops;
@@ -241,164 +233,8 @@ int pinmux_gpio_direction(struct pinctrl_dev *pctldev,
return ret;
}
-/**
- * acquire_pins() - acquire all the pins for a certain function on a pinmux
- * @pctldev: the device to take the pins on
- * @owner: a representation of the owner of this pin; typically the device
- * name that controls its mux function
- * @group_selector: the group selector containing the pins to acquire
- */
-static int acquire_pins(struct pinctrl_dev *pctldev,
- const char *owner,
- unsigned group_selector)
-{
- const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
- const unsigned *pins;
- unsigned num_pins;
- int ret;
- int i;
-
- ret = pctlops->get_group_pins(pctldev, group_selector,
- &pins, &num_pins);
- if (ret)
- return ret;
-
- 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], owner, NULL);
- if (ret) {
- dev_err(pctldev->dev,
- "could not get request pin %d on device %s - conflicting mux mappings?\n",
- pins[i],
- pinctrl_dev_get_name(pctldev));
- /* On error release all taken pins */
- i--; /* this pin just failed */
- for (; i >= 0; i--)
- pin_free(pctldev, pins[i], NULL);
- return -ENODEV;
- }
- }
- return 0;
-}
-
-/**
- * release_pins() - release pins taken by earlier acquirement
- * @pctldev: the device to free the pins on
- * @group_selector: the group selector containing the pins to free
- */
-static void release_pins(struct pinctrl_dev *pctldev,
- unsigned group_selector)
-{
- const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
- const unsigned *pins;
- unsigned num_pins;
- int ret;
- int i;
-
- ret = pctlops->get_group_pins(pctldev, group_selector,
- &pins, &num_pins);
- if (ret) {
- dev_err(pctldev->dev, "could not get pins to release for group selector %d\n",
- group_selector);
- return;
- }
- for (i = 0; i < num_pins; i++)
- pin_free(pctldev, pins[i], NULL);
-}
-
-/**
- * pinmux_check_pin_group() - check function and pin group combo
- * @pctldev: device to check the pin group vs function for
- * @func_selector: the function selector to check the pin group for, we have
- * already looked this up in the calling function
- * @pin_group: the pin group to match to the function
- *
- * This function will check that the pinmux driver can supply the
- * selected pin group for a certain function, returns the group selector if
- * the group and function selector will work fine together, else returns
- * negative
- */
-static int pinmux_check_pin_group(struct pinctrl_dev *pctldev,
- unsigned func_selector,
- const char *pin_group)
-{
- const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
- const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
- int ret;
-
- /*
- * If the driver does not support different pin groups for the
- * functions, we only support group 0, and assume this exists.
- */
- if (!pctlops || !pctlops->list_groups)
- return 0;
-
- /*
- * Passing NULL (no specific group) will select the first and
- * hopefully only group of pins available for this function.
- */
- if (!pin_group) {
- char const * const *groups;
- unsigned num_groups;
-
- ret = pmxops->get_function_groups(pctldev, func_selector,
- &groups, &num_groups);
- if (ret)
- return ret;
- if (num_groups < 1)
- return -EINVAL;
- ret = pinctrl_get_group_selector(pctldev, groups[0]);
- if (ret < 0) {
- 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),
- groups[0]);
- return ret;
- }
-
- if (num_groups > 1)
- 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),
- groups[0],
- ret);
-
- return ret;
- }
-
- 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,
- "%s does not support pin group %s with function %s\n",
- pinctrl_dev_get_name(pctldev),
- pin_group,
- pmxops->get_function_name(pctldev, func_selector));
- }
- return ret;
-}
-
-/**
- * pinmux_search_function() - check pin control driver for a certain function
- * @pctldev: device to check for function and position
- * @map: function map containing the function and position to look for
- * @func_selector: returns the applicable function selector if found
- * @group_selector: returns the applicable group selector if found
- *
- * This will search the pinmux driver for an applicable
- * function with a specific pin group, returns 0 if these can be mapped
- * negative otherwise
- */
-static int pinmux_search_function(struct pinctrl_dev *pctldev,
- struct pinctrl_map const *map,
- unsigned *func_selector,
- unsigned *group_selector)
+int pinmux_func_name_to_selector(struct pinctrl_dev *pctldev,
+ const char *function)
{
const struct pinmux_ops *ops = pctldev->desc->pmxops;
unsigned selector = 0;
@@ -407,168 +243,128 @@ static int pinmux_search_function(struct pinctrl_dev *pctldev,
while (ops->list_functions(pctldev, selector) >= 0) {
const char *fname = ops->get_function_name(pctldev,
selector);
- int ret;
-
- if (!strcmp(map->function, fname)) {
- /* Found the function, check pin group */
- ret = pinmux_check_pin_group(pctldev, selector,
- map->group);
- if (ret < 0)
- return ret;
- /* This function and group selector can be used */
- *func_selector = selector;
- *group_selector = ret;
- return 0;
+ if (!strcmp(function, fname))
+ return selector;
- }
selector++;
}
pr_err("%s does not support function %s\n",
- pinctrl_dev_get_name(pctldev), map->function);
+ pinctrl_dev_get_name(pctldev), function);
return -EINVAL;
}
-/**
- * pinmux_enable_muxmap() - enable a map entry for a certain pinmux
- */
-static int pinmux_enable_muxmap(struct pinctrl_dev *pctldev,
- struct pinctrl *p,
- struct device *dev,
- const char *devname,
- struct pinctrl_map const *map)
+int pinmux_map_to_setting(struct pinctrl_map const *map,
+ struct pinctrl_setting *setting)
{
- unsigned func_selector;
- unsigned group_selector;
- struct pinmux_group *grp;
+ struct pinctrl_dev *pctldev = setting->pctldev;
+ const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
+ const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
+ char const * const *groups;
+ unsigned num_groups;
int ret;
+ const char *group;
+ int i;
+ const unsigned *pins;
+ unsigned num_pins;
- /*
- * Note that we're not locking the pinmux mutex here, because
- * this is only called at pinmux initialization time when it
- * has not been added to any list and thus is not reachable
- * by anyone else.
- */
+ setting->func_selector =
+ pinmux_func_name_to_selector(pctldev, map->function);
+ if (setting->func_selector < 0)
+ return setting->func_selector;
- if (p->pctldev && p->pctldev != pctldev) {
- dev_err(pctldev->dev,
- "different pin control devices given for device %s, function %s\n",
- devname, map->function);
+ ret = pmxops->get_function_groups(pctldev, setting->func_selector,
+ &groups, &num_groups);
+ if (ret < 0)
+ return ret;
+ if (!num_groups)
return -EINVAL;
+
+ if (map->group) {
+ bool found = false;
+ group = map->group;
+ for (i = 0; i < num_groups; i++) {
+ if (!strcmp(group, groups[i])) {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ return -EINVAL;
+ } else {
+ group = groups[0];
}
- p->dev = dev;
- p->pctldev = pctldev;
- /* Now go into the driver and try to match a function and group */
- ret = pinmux_search_function(pctldev, map, &func_selector,
- &group_selector);
- if (ret < 0)
- return ret;
+ setting->group_selector =
+ pinctrl_get_group_selector(pctldev, group);
+ if (setting->group_selector < 0)
+ return setting->group_selector;
- /*
- * If the function selector is already set, it needs to be identical,
- * we support several groups with one function but not several
- * functions with one or several groups in the same pinmux.
- */
- if (p->func_selector != UINT_MAX &&
- p->func_selector != func_selector) {
+ ret = pctlops->get_group_pins(pctldev, setting->group_selector,
+ &pins, &num_pins);
+ if (ret) {
dev_err(pctldev->dev,
- "dual function defines in the map for device %s\n",
- devname);
- return -EINVAL;
+ "could not get pins for device %s group selector %d\n",
+ pinctrl_dev_get_name(pctldev), setting->group_selector);
+ return -ENODEV;
}
- p->func_selector = func_selector;
-
- /* Now add this group selector, we may have many of them */
- grp = kmalloc(sizeof(*grp), GFP_KERNEL);
- if (!grp)
- return -ENOMEM;
- grp->group_selector = group_selector;
- ret = acquire_pins(pctldev, devname, group_selector);
- if (ret) {
- kfree(grp);
- return ret;
+
+ /* Try to allocate all pins in this group, one by one */
+ for (i = 0; i < num_pins; i++) {
+ ret = pin_request(pctldev, pins[i], map->dev_name, NULL);
+ if (ret) {
+ dev_err(pctldev->dev,
+ "could not get request pin %d on device %s\n",
+ pins[i], pinctrl_dev_get_name(pctldev));
+ /* On error release all taken pins */
+ i--; /* this pin just failed */
+ for (; i >= 0; i--)
+ pin_free(pctldev, pins[i], NULL);
+ return -ENODEV;
+ }
}
- list_add_tail(&grp->node, &p->groups);
return 0;
}
-/**
- * pinmux_apply_muxmap() - apply a certain mux mapping entry
- */
-int pinmux_apply_muxmap(struct pinctrl_dev *pctldev,
- struct pinctrl *p,
- struct device *dev,
- const char *devname,
- struct pinctrl_map const *map)
+void pinmux_free_setting(struct pinctrl_setting const *setting)
{
+ struct pinctrl_dev *pctldev = setting->pctldev;
+ const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
+ const unsigned *pins;
+ unsigned num_pins;
int ret;
+ int i;
- ret = pinmux_enable_muxmap(pctldev, p, dev,
- devname, map);
+ ret = pctlops->get_group_pins(pctldev, setting->group_selector,
+ &pins, &num_pins);
if (ret) {
- pinmux_put(p);
- return ret;
+ dev_err(pctldev->dev,
+ "could not get pins for device %s group selector %d\n",
+ pinctrl_dev_get_name(pctldev), setting->group_selector);
+ return;
}
- return 0;
-}
-
-/**
- * pinmux_put() - free up the pinmux portions of a pin controller handle
- */
-void pinmux_put(struct pinctrl *p)
-{
- struct list_head *node, *tmp;
-
- list_for_each_safe(node, tmp, &p->groups) {
- struct pinmux_group *grp =
- list_entry(node, struct pinmux_group, node);
- /* Release all pins taken by this group */
- release_pins(p->pctldev, grp->group_selector);
- list_del(node);
- kfree(grp);
- }
+ for (i = 0; i < num_pins; i++)
+ pin_free(pctldev, pins[i], NULL);
}
-/**
- * pinmux_enable() - enable the pinmux portion of a pin control handle
- */
-int pinmux_enable(struct pinctrl *p)
+int pinmux_enable_setting(struct pinctrl_setting const *setting)
{
- struct pinctrl_dev *pctldev = p->pctldev;
+ struct pinctrl_dev *pctldev = setting->pctldev;
const struct pinmux_ops *ops = pctldev->desc->pmxops;
- struct pinmux_group *grp;
- int ret;
- list_for_each_entry(grp, &p->groups, node) {
- ret = ops->enable(pctldev, p->func_selector,
- grp->group_selector);
- if (ret)
- /*
- * TODO: call disable() on all groups we called
- * enable() on to this point?
- */
- return ret;
- }
- return 0;
+ return ops->enable(pctldev, setting->func_selector,
+ setting->group_selector);
}
-/**
- * pinmux_disable() - disable the pinmux portions of a pin control handle
- */
-void pinmux_disable(struct pinctrl *p)
+void pinmux_disable_setting(struct pinctrl_setting const *setting)
{
- struct pinctrl_dev *pctldev = p->pctldev;
+ struct pinctrl_dev *pctldev = setting->pctldev;
const struct pinmux_ops *ops = pctldev->desc->pmxops;
- struct pinmux_group *grp;
- list_for_each_entry(grp, &p->groups, node) {
- ops->disable(pctldev, p->func_selector,
- grp->group_selector);
- }
+ ops->disable(pctldev, setting->func_selector, setting->group_selector);
}
#ifdef CONFIG_DEBUG_FS
@@ -639,29 +435,18 @@ static int pinmux_pins_show(struct seq_file *s, void *what)
return 0;
}
-void pinmux_dbg_show(struct seq_file *s, struct pinctrl *p)
+void pinmux_dbg_show(struct seq_file *s, struct pinctrl_setting const *setting)
{
- struct pinctrl_dev *pctldev = p->pctldev;
- const struct pinmux_ops *pmxops;
- const struct pinctrl_ops *pctlops;
- struct pinmux_group *grp;
-
- pmxops = pctldev->desc->pmxops;
- pctlops = pctldev->desc->pctlops;
-
- seq_printf(s, " function: %s (%u),",
- pmxops->get_function_name(pctldev,
- p->func_selector),
- p->func_selector);
-
- seq_printf(s, " groups: [");
- list_for_each_entry(grp, &p->groups, node) {
- seq_printf(s, " %s (%u)",
- pctlops->get_group_name(pctldev,
- grp->group_selector),
- grp->group_selector);
- }
- seq_printf(s, " ]");
+ struct pinctrl_dev *pctldev = setting->pctldev;
+ const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
+ const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
+
+ seq_printf(s, "controller: %s group: %s (%u) function: %s (%u)\n",
+ pinctrl_dev_get_name(pctldev),
+ pctlops->get_group_name(pctldev, setting->group_selector),
+ setting->group_selector,
+ pmxops->get_function_name(pctldev, setting->func_selector),
+ setting->func_selector);
}
static int pinmux_functions_open(struct inode *inode, struct file *file)
diff --git a/drivers/pinctrl/pinmux.h b/drivers/pinctrl/pinmux.h
index 84b8fe9..1500ae8 100644
--- a/drivers/pinctrl/pinmux.h
+++ b/drivers/pinctrl/pinmux.h
@@ -13,6 +13,7 @@
#ifdef CONFIG_PINMUX
int pinmux_check_ops(struct pinctrl_dev *pctldev);
+
int pinmux_request_gpio(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned pin, unsigned gpio);
@@ -21,22 +22,16 @@ void pinmux_free_gpio(struct pinctrl_dev *pctldev, unsigned pin,
int pinmux_gpio_direction(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned pin, bool input);
-static inline void pinmux_init_pinctrl_handle(struct pinctrl *p)
-{
- p->func_selector = UINT_MAX;
- INIT_LIST_HEAD(&p->groups);
-}
-int pinmux_apply_muxmap(struct pinctrl_dev *pctldev,
- struct pinctrl *p,
- struct device *dev,
- const char *devname,
- struct pinctrl_map const *map);
-void pinmux_put(struct pinctrl *p);
-int pinmux_enable(struct pinctrl *p);
-void pinmux_disable(struct pinctrl *p);
+
+int pinmux_map_to_setting(struct pinctrl_map const *map,
+ struct pinctrl_setting *setting);
+void pinmux_free_setting(struct pinctrl_setting const *setting);
+int pinmux_enable_setting(struct pinctrl_setting const *setting);
+void pinmux_disable_setting(struct pinctrl_setting const *setting);
+
+void pinmux_dbg_show(struct seq_file *s, struct pinctrl_setting const *setting);
void pinmux_init_device_debugfs(struct dentry *devroot,
struct pinctrl_dev *pctldev);
-void pinmux_dbg_show(struct seq_file *s, struct pinctrl *p);
#else
@@ -65,28 +60,23 @@ static inline int pinmux_gpio_direction(struct pinctrl_dev *pctldev,
return 0;
}
-static inline void pinmux_init_pinctrl_handle(struct pinctrl *p)
-{
-}
-
-static inline int pinmux_apply_muxmap(struct pinctrl_dev *pctldev,
- struct pinctrl *p,
- struct device *dev,
- const char *devname,
- struct pinctrl_map const *map)
+static inline int pinmux_map_to_setting(struct pinctrl_map const *map,
+ struct pinctrl_setting *setting)
{
return 0;
}
-static inline void pinmux_put(struct pinctrl *p)
+static inline void pinmux_free_setting(struct pinctrl_setting const *setting)
{
}
-static inline int pinmux_enable(struct pinctrl *p)
+static inline int pinmux_enable_setting(struct pinctrl_setting const *setting)
{
+ return 0;
}
-static inline void pinmux_disable(struct pinctrl *p)
+static inline void pinmux_disable_setting(
+ struct pinctrl_setting const *setting)
{
}
--
1.7.5.4
Multiple mapping table entries could reference the same pin, and hence
"own" it. This would be unusual now that pinctrl_get() represents a single
state for a client device, but in the future when it represents all known
states for a device, this is quite likely. Implement reference counting
for pin ownership to handle this.
Signed-off-by: Stephen Warren <[email protected]>
---
drivers/pinctrl/core.h | 1 +
drivers/pinctrl/pinmux.c | 29 ++++++++++++++++++++++-------
2 files changed, 23 insertions(+), 7 deletions(-)
diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h
index 1290995..64ae1b8 100644
--- a/drivers/pinctrl/core.h
+++ b/drivers/pinctrl/core.h
@@ -92,6 +92,7 @@ struct pin_desc {
bool dynamic_name;
/* These fields only added when supporting pinmux drivers */
#ifdef CONFIG_PINMUX
+ unsigned usecount;
const char *owner;
#endif
};
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c
index 8d32380..359f6ac 100644
--- a/drivers/pinctrl/pinmux.c
+++ b/drivers/pinctrl/pinmux.c
@@ -83,11 +83,16 @@ static int pin_request(struct pinctrl_dev *pctldev,
goto out;
}
- if (desc->owner && strcmp(desc->owner, owner)) {
+ if (desc->usecount && strcmp(desc->owner, owner)) {
dev_err(pctldev->dev,
"pin already requested\n");
goto out;
}
+
+ desc->usecount++;
+ if (desc->usecount > 1)
+ return 0;
+
desc->owner = owner;
/* Let each pin increase references to this module */
@@ -100,9 +105,9 @@ static int pin_request(struct pinctrl_dev *pctldev,
}
/*
- * If there is no kind of request function for the pin we just assume
- * we got it by default and proceed.
- */
+ * If there is no kind of request function for the pin we just assume
+ * we got it by default and proceed.
+ */
if (gpio_range && ops->gpio_request_enable)
/* This requests and enables a single GPIO pin */
status = ops->gpio_request_enable(pctldev, gpio_range, pin);
@@ -111,12 +116,18 @@ static int pin_request(struct pinctrl_dev *pctldev,
else
status = 0;
- if (status)
+ if (status) {
dev_err(pctldev->dev, "->request on device %s failed for pin %d\n",
pctldev->desc->name, pin);
+ module_put(pctldev->owner);
+ }
+
out_free_pin:
- if (status)
- desc->owner = NULL;
+ if (status) {
+ desc->usecount--;
+ if (!desc->usecount)
+ desc->owner = NULL;
+ }
out:
if (status)
dev_err(pctldev->dev, "pin-%d (%s) status %d\n",
@@ -150,6 +161,10 @@ static const char *pin_free(struct pinctrl_dev *pctldev, int pin,
return NULL;
}
+ desc->usecount--;
+ if (desc->usecount)
+ return NULL;
+
/*
* If there is no kind of request function for the pin we just assume
* we got it by default and proceed.
--
1.7.5.4
* Make all functions internal to core.c static. Remove any of these from
core.h.
* Add any missing EXPORT_SYMBOL_GPL().
Signed-off-by: Stephen Warren <[email protected]>
---
drivers/pinctrl/core.c | 12 +++++++-----
drivers/pinctrl/core.h | 3 ---
2 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index 50bcc51..b6e3c35 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -293,9 +293,9 @@ pinctrl_match_gpio_range(struct pinctrl_dev *pctldev, unsigned gpio)
* the GPIO subsystem, return the device and the matching GPIO range. Returns
* negative if the GPIO range could not be found in any device.
*/
-int pinctrl_get_device_gpio_range(unsigned gpio,
- struct pinctrl_dev **outdev,
- struct pinctrl_gpio_range **outrange)
+static int pinctrl_get_device_gpio_range(unsigned gpio,
+ struct pinctrl_dev **outdev,
+ struct pinctrl_gpio_range **outrange)
{
struct pinctrl_dev *pctldev = NULL;
@@ -332,6 +332,7 @@ void pinctrl_add_gpio_range(struct pinctrl_dev *pctldev,
list_add_tail(&range->node, &pctldev->gpio_ranges);
mutex_unlock(&pctldev->gpio_ranges_lock);
}
+EXPORT_SYMBOL_GPL(pinctrl_add_gpio_range);
/**
* pinctrl_remove_gpio_range() - remove a range of GPIOs fro a pin controller
@@ -345,6 +346,7 @@ void pinctrl_remove_gpio_range(struct pinctrl_dev *pctldev,
list_del(&range->node);
mutex_unlock(&pctldev->gpio_ranges_lock);
}
+EXPORT_SYMBOL_GPL(pinctrl_remove_gpio_range);
/**
* pinctrl_get_group_selector() - returns the group selector for a group
@@ -785,7 +787,7 @@ static int pinctrl_hog_map(struct pinctrl_dev *pctldev,
* map entries that need to be hogged, i.e. get+enabled until the system shuts
* down.
*/
-int pinctrl_hog_maps(struct pinctrl_dev *pctldev)
+static int pinctrl_hog_maps(struct pinctrl_dev *pctldev)
{
struct device *dev = pctldev->dev;
const char *devname = dev_name(dev);
@@ -819,7 +821,7 @@ int pinctrl_hog_maps(struct pinctrl_dev *pctldev)
* pinctrl_unhog_maps() - unhog specific map entries on controller device
* @pctldev: the pin control device to unhog entries on
*/
-void pinctrl_unhog_maps(struct pinctrl_dev *pctldev)
+static void pinctrl_unhog_maps(struct pinctrl_dev *pctldev)
{
struct list_head *node, *tmp;
diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h
index de4c3ed..061c57d 100644
--- a/drivers/pinctrl/core.h
+++ b/drivers/pinctrl/core.h
@@ -101,8 +101,5 @@ struct pin_desc {
struct pinctrl_dev *get_pinctrl_dev_from_devname(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);
int pinctrl_get_group_selector(struct pinctrl_dev *pctldev,
const char *pin_group);
--
1.7.5.4
Modify the two files so that the order of function prototypes in the
header matches the order of implementations in the .c file.
Don't prototype a couple of internal functions.
Signed-off-by: Stephen Warren <[email protected]>
---
drivers/pinctrl/pinconf.c | 31 +++++++++++++++----------------
drivers/pinctrl/pinconf.h | 5 +----
2 files changed, 16 insertions(+), 20 deletions(-)
diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c
index b74f64a..0c9d08d 100644
--- a/drivers/pinctrl/pinconf.c
+++ b/drivers/pinctrl/pinconf.c
@@ -23,7 +23,20 @@
#include "core.h"
#include "pinconf.h"
-int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
+int pinconf_check_ops(struct pinctrl_dev *pctldev)
+{
+ const struct pinconf_ops *ops = pctldev->desc->confops;
+
+ /* 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;
+}
+
+static int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
unsigned long *config)
{
const struct pinconf_ops *ops = pctldev->desc->confops;
@@ -63,7 +76,7 @@ int pin_config_get(const char *dev_name, const char *name,
}
EXPORT_SYMBOL(pin_config_get);
-int pin_config_set_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
+static int pin_config_set_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
unsigned long config)
{
const struct pinconf_ops *ops = pctldev->desc->confops;
@@ -138,7 +151,6 @@ int pin_config_group_get(const char *dev_name, const char *pin_group,
}
EXPORT_SYMBOL(pin_config_group_get);
-
int pin_config_group_set(const char *dev_name, const char *pin_group,
unsigned long config)
{
@@ -205,19 +217,6 @@ int pin_config_group_set(const char *dev_name, const char *pin_group,
}
EXPORT_SYMBOL(pin_config_group_set);
-int pinconf_check_ops(struct pinctrl_dev *pctldev)
-{
- const struct pinconf_ops *ops = pctldev->desc->confops;
-
- /* 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,
diff --git a/drivers/pinctrl/pinconf.h b/drivers/pinctrl/pinconf.h
index 006b77f..1d6ea9d 100644
--- a/drivers/pinctrl/pinconf.h
+++ b/drivers/pinctrl/pinconf.h
@@ -14,12 +14,9 @@
#ifdef CONFIG_PINCONF
int pinconf_check_ops(struct pinctrl_dev *pctldev);
+
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
--
1.7.5.4
This hopefully makes it harder to take the sizeof the wrong type.
Signed-off-by: Stephen Warren <[email protected]>
---
drivers/pinctrl/core.c | 8 ++++----
drivers/pinctrl/pinmux.c | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index 5a435f4..b8e6112 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -502,7 +502,7 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev, const char *name)
* mapping, this is what consumers will get when requesting
* a pin control handle with pinctrl_get()
*/
- p = kzalloc(sizeof(struct pinctrl), GFP_KERNEL);
+ p = kzalloc(sizeof(*p), GFP_KERNEL);
if (p == NULL) {
dev_err(dev, "failed to alloc struct pinctrl\n");
return ERR_PTR(-ENOMEM);
@@ -522,7 +522,7 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev, const char *name)
pinmux_put(p);
kfree(p);
/* Eventually, this should trigger deferred probe */
- return -ENODEV;
+ return ERR_PTR(-ENODEV);
}
dev_dbg(dev, "in map, found pctldev %s to handle function %s",
@@ -719,7 +719,7 @@ static int pinctrl_hog_map(struct pinctrl_dev *pctldev,
struct pinctrl *p;
int ret;
- hog = kzalloc(sizeof(struct pinctrl_hog), GFP_KERNEL);
+ hog = kzalloc(sizeof(*hog), GFP_KERNEL);
if (!hog) {
dev_err(pctldev->dev, "failed to alloc struct pinctrl_hog\n");
return -ENOMEM;
@@ -1153,7 +1153,7 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
if (pctldesc->name == NULL)
return NULL;
- pctldev = kzalloc(sizeof(struct pinctrl_dev), GFP_KERNEL);
+ pctldev = kzalloc(sizeof(*pctldev), GFP_KERNEL);
if (pctldev == NULL) {
dev_err(dev, "failed to alloc struct pinctrl_dev\n");
return NULL;
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c
index 2887897..98b89d6 100644
--- a/drivers/pinctrl/pinmux.c
+++ b/drivers/pinctrl/pinmux.c
@@ -491,7 +491,7 @@ static int pinmux_enable_muxmap(struct pinctrl_dev *pctldev,
p->func_selector = func_selector;
/* Now add this group selector, we may have many of them */
- grp = kmalloc(sizeof(struct pinmux_group), GFP_KERNEL);
+ grp = kmalloc(sizeof(*grp), GFP_KERNEL);
if (!grp)
return -ENOMEM;
grp->group_selector = group_selector;
--
1.7.5.4
e.g. dev_err instead of pr_err prints messages in a slightly more
standardized format.
Also, add a few more error messages to track down errors.
Also, some small cleanups of messages.
Signed-off-by: Stephen Warren <[email protected]>
---
drivers/pinctrl/core.c | 38 ++++++++++++++++++++++----------------
1 files changed, 22 insertions(+), 16 deletions(-)
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index 54e24f7..ce6016d 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -212,8 +212,10 @@ static int pinctrl_register_one_pin(struct pinctrl_dev *pctldev,
}
pindesc = kzalloc(sizeof(*pindesc), GFP_KERNEL);
- if (pindesc == NULL)
+ if (pindesc == NULL) {
+ dev_err(pctldev->dev, "failed to alloc struct pin_desc\n");
return -ENOMEM;
+ }
spin_lock_init(&pindesc->lock);
@@ -493,7 +495,7 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev, const char *name)
devname = dev_name(dev);
- pr_debug("get pin control handle device %s state %s\n", devname, name);
+ dev_dbg(dev, "pinctrl_get() for state %s\n", name);
/*
* create the state cookie holder struct pinctrl for each
@@ -501,8 +503,10 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev, const char *name)
* a pin control handle with pinctrl_get()
*/
p = kzalloc(sizeof(struct pinctrl), GFP_KERNEL);
- if (p == NULL)
+ if (p == NULL) {
+ dev_err(dev, "failed to alloc struct pinctrl\n");
return ERR_PTR(-ENOMEM);
+ }
mutex_init(&p->mutex);
pinmux_init_pinctrl_handle(p);
@@ -513,17 +517,15 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev, const char *name)
*/
pctldev = get_pinctrl_dev_from_devname(map->ctrl_dev_name);
if (!pctldev) {
- pr_warning("could not find a pinctrl device for pinmux function %s, fishy, they shall all have one\n",
- map->function);
- pr_warning("given pinctrl device name: %s",
- map->ctrl_dev_name);
+ dev_warn(dev, "unknown pinctrl device %s in map entry",
+ map->ctrl_dev_name);
/* Continue to check the other mappings anyway... */
continue;
}
- pr_debug("in map, found pctldev %s to handle function %s",
- dev_name(pctldev->dev), map->function);
+ dev_dbg(dev, "in map, found pctldev %s to handle function %s",
+ dev_name(pctldev->dev), map->function);
/* Map must be for this device */
if (strcmp(map->dev_name, devname))
@@ -553,8 +555,7 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev, const char *name)
if (!num_maps)
dev_info(dev, "zero maps found for state %s\n", name);
- pr_debug("found %u mux maps for device %s, UD %s\n",
- num_maps, devname, name);
+ dev_dbg(dev, "found %u maps for state %s\n", num_maps, name);
/* Add the pinmux to the global list */
mutex_lock(&pinctrl_list_mutex);
@@ -665,7 +666,7 @@ int pinctrl_register_mappings(struct pinctrl_map const *maps,
for (i = 0; i < num_maps; i++) {
if (!maps[i].name) {
pr_err("failed to register map %d: no map name given\n",
- i);
+ i);
return -EINVAL;
}
@@ -677,13 +678,13 @@ int pinctrl_register_mappings(struct pinctrl_map const *maps,
if (!maps[i].function) {
pr_err("failed to register map %s (%d): no function ID given\n",
- maps[i].name, i);
+ maps[i].name, i);
return -EINVAL;
}
if (!maps[i].dev_name) {
pr_err("failed to register map %s (%d): no device given\n",
- maps[i].name, i);
+ maps[i].name, i);
return -EINVAL;
}
}
@@ -697,6 +698,7 @@ int pinctrl_register_mappings(struct pinctrl_map const *maps,
maps_node->num_maps = num_maps;
maps_node->maps = kmemdup(maps, sizeof(*maps) * num_maps, GFP_KERNEL);
if (!maps_node->maps) {
+ pr_err("failed to duplicate mapping table\n");
kfree(maps_node);
return -ENOMEM;
}
@@ -717,8 +719,10 @@ static int pinctrl_hog_map(struct pinctrl_dev *pctldev,
int ret;
hog = kzalloc(sizeof(struct pinctrl_hog), GFP_KERNEL);
- if (!hog)
+ if (!hog) {
+ dev_err(pctldev->dev, "failed to alloc struct pinctrl_hog\n");
return -ENOMEM;
+ }
p = pinctrl_get_locked(pctldev->dev, map->name);
if (IS_ERR(p)) {
@@ -1149,8 +1153,10 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
return NULL;
pctldev = kzalloc(sizeof(struct pinctrl_dev), GFP_KERNEL);
- if (pctldev == NULL)
+ if (pctldev == NULL) {
+ dev_err(dev, "failed to alloc struct pinctrl_dev\n");
return NULL;
+ }
/* Initialize pin control device struct */
pctldev->owner = pctldesc->owner;
--
1.7.5.4
This may be perfectly legitimate. An IP block may get re-used
across SoCs. Not all of those SoCs may need pinmux settings for the
IP block, e.g. if one SoC dedicates pins to that function but
another doesn't. The driver won't know this, and will always
attempt to set up the pinmux. The mapping table defines whether any
HW programming is actually needed.
Signed-off-by: Stephen Warren <[email protected]>
---
drivers/pinctrl/core.c | 17 ++++++++++-------
1 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index 37dfac7..54e24f7 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -542,13 +542,16 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev, const char *name)
num_maps++;
}
- /* We should have atleast one map, right */
- if (!num_maps) {
- pr_err("could not find any mux maps for device %s, ID %s\n",
- devname, name);
- kfree(p);
- return ERR_PTR(-EINVAL);
- }
+ /*
+ * This may be perfectly legitimate. An IP block may get re-used
+ * across SoCs. Not all of those SoCs may need pinmux settings for the
+ * IP block, e.g. if one SoC dedicates pins to that function but
+ * another doesn't. The driver won't know this, and will always
+ * attempt to set up the pinmux. The mapping table defines whether any
+ * HW programming is actually needed.
+ */
+ if (!num_maps)
+ dev_info(dev, "zero maps found for state %s\n", name);
pr_debug("found %u mux maps for device %s, UD %s\n",
num_maps, devname, name);
--
1.7.5.4
This is a serious error, and the pin control system will not function
correctly if it ends up not programing the mapping table entries into
the HW. Instead of just ignoring this, error out.
Signed-off-by: Stephen Warren <[email protected]>
---
drivers/pinctrl/core.c | 11 ++++++-----
1 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index ce6016d..5a435f4 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -517,11 +517,12 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev, const char *name)
*/
pctldev = get_pinctrl_dev_from_devname(map->ctrl_dev_name);
if (!pctldev) {
- dev_warn(dev, "unknown pinctrl device %s in map entry",
- map->ctrl_dev_name);
-
- /* Continue to check the other mappings anyway... */
- continue;
+ dev_err(dev, "unknown pinctrl device %s in map entry",
+ map->ctrl_dev_name);
+ pinmux_put(p);
+ kfree(p);
+ /* Eventually, this should trigger deferred probe */
+ return -ENODEV;
}
dev_dbg(dev, "in map, found pctldev %s to handle function %s",
--
1.7.5.4
Hog entries are mapping table entries with .ctrl_dev_name == .dev_name.
All other mapping table entries need .dev_name set so that they will
match some pinctrl_get() call. All extant PIN_MAP*() macros set
.dev_name.
So, there is no reason to allow mapping table entries without .dev_name
set. Update the code and documentation to disallow this.
Signed-off-by: Stephen Warren <[email protected]>
---
Documentation/pinctrl.txt | 15 +++-----
drivers/pinctrl/core.c | 75 ++++++++++++--------------------------
include/linux/pinctrl/machine.h | 7 ----
3 files changed, 29 insertions(+), 68 deletions(-)
diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt
index bfe83b1..12b35db 100644
--- a/Documentation/pinctrl.txt
+++ b/Documentation/pinctrl.txt
@@ -494,14 +494,10 @@ Definitions:
{"map-i2c0", i2c0, pinctrl0, fi2c0, gi2c0}
}
- Every map must be assigned a symbolic name, pin controller and function.
- The group is not compulsory - if it is omitted the first group presented by
- the driver as applicable for the function will be selected, which is
- useful for simple cases.
-
- The device name is present in map entries tied to specific devices. Maps
- without device names are referred to as SYSTEM pinmuxes, such as can be taken
- by the machine implementation on boot and not tied to any specific device.
+ Every map must be assigned a state name, pin controller, device and
+ function. The group is not compulsory - if it is omitted the first group
+ presented by the driver as applicable for the function will be selected,
+ which is useful for simple cases.
It is possible to map several groups to the same combination of device,
pin controller and function. This is for cases where a certain function on
@@ -979,8 +975,7 @@ after this you should be able to see this in the debugfs listing of all pins.
System pin control hogging
==========================
-A system pin control map entry, i.e. a pin control setting that does not have
-a device associated with it, can be hogged by the core when the pin controller
+Pin control map entries can be hogged by the core when the pin controller
is registered. This means that the core will attempt to call pinctrl_get() and
pinctrl_enable() on it immediately after the pin control device has been
registered.
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index 5e30d91..331ffb6 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -479,24 +479,21 @@ EXPORT_SYMBOL_GPL(pinctrl_gpio_direction_output);
static struct pinctrl *pinctrl_get_locked(struct device *dev, const char *name)
{
struct pinctrl_dev *pctldev = NULL;
- const char *devname = NULL;
+ const char *devname;
struct pinctrl *p;
- bool found_map;
unsigned num_maps = 0;
int ret = -ENODEV;
struct pinctrl_maps *maps_node;
int i;
struct pinctrl_map const *map;
- /* We must have a state name */
- if (WARN_ON(!name))
+ /* We must have both dev and state name */
+ if (WARN_ON(!dev || !name))
return ERR_PTR(-EINVAL);
- if (dev)
- devname = dev_name(dev);
+ devname = dev_name(dev);
- pr_debug("get pin control handle %s for device %s\n", name,
- devname ? devname : "(none)");
+ pr_debug("get pin control handle device %s state %s\n", devname, name);
/*
* create the state cookie holder struct pinctrl for each
@@ -511,8 +508,6 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev, const char *name)
/* Iterate over the pin control maps to locate the right ones */
for_each_maps(maps_node, i, map) {
- found_map = false;
-
/*
* First, try to find the pctldev given in the map
*/
@@ -530,47 +525,33 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev, const char *name)
pr_debug("in map, found pctldev %s to handle function %s",
dev_name(pctldev->dev), map->function);
+ /* Map must be for this device */
+ if (strcmp(map->dev_name, devname))
+ continue;
+
/* State name must be the one we're looking for */
if (strcmp(map->name, name))
continue;
- /*
- * This is for the case where no device name is given, we
- * already know that the function name matches from above
- * code.
- */
- if (!map->dev_name)
- found_map = true;
-
- /* If the mapping has a device set up it must match */
- if (map->dev_name &&
- (!devname || !strcmp(map->dev_name, devname)))
- /* MATCH! */
- found_map = true;
-
- /* If this map is applicable, then apply it */
- if (found_map) {
- ret = pinmux_apply_muxmap(pctldev, p, dev,
- devname, map);
- if (ret) {
- kfree(p);
- return ERR_PTR(ret);
- }
- num_maps++;
+ ret = pinmux_apply_muxmap(pctldev, p, dev,
+ devname, map);
+ if (ret) {
+ kfree(p);
+ return ERR_PTR(ret);
}
+ num_maps++;
}
/* We should have atleast one map, right */
if (!num_maps) {
pr_err("could not find any mux maps for device %s, ID %s\n",
- devname ? devname : "(anonymous)", name);
+ devname, name);
kfree(p);
return ERR_PTR(-EINVAL);
}
pr_debug("found %u mux maps for device %s, UD %s\n",
- num_maps,
- devname ? devname : "(anonymous)", name);
+ num_maps, devname, name);
/* Add the pinmux to the global list */
mutex_lock(&pinctrl_list_mutex);
@@ -697,14 +678,11 @@ int pinctrl_register_mappings(struct pinctrl_map const *maps,
return -EINVAL;
}
- if (!maps[i].dev_name)
- pr_debug("add system map %s function %s with no device\n",
- maps[i].name,
- maps[i].function);
- else
- pr_debug("register map %s, function %s\n",
- maps[i].name,
- maps[i].function);
+ if (!maps[i].dev_name) {
+ pr_err("failed to register map %s (%d): no device given\n",
+ maps[i].name, i);
+ return -EINVAL;
+ }
}
maps_node = kzalloc(sizeof(*maps_node), GFP_KERNEL);
@@ -929,13 +907,8 @@ static int pinctrl_maps_show(struct seq_file *s, void *what)
mutex_lock(&pinctrl_maps_mutex);
for_each_maps(maps_node, i, map) {
seq_printf(s, "%s:\n", map->name);
- if (map->dev_name)
- seq_printf(s, " device: %s\n",
- map->dev_name);
- else
- seq_printf(s, " SYSTEM MUX\n");
- seq_printf(s, " controlling device %s\n",
- map->ctrl_dev_name);
+ seq_printf(s, " device: %s\n", map->dev_name);
+ seq_printf(s, " controlling device %s\n", map->ctrl_dev_name);
seq_printf(s, " function: %s\n", map->function);
seq_printf(s, " group: %s\n", map->group ? map->group :
"(default)");
diff --git a/include/linux/pinctrl/machine.h b/include/linux/pinctrl/machine.h
index af145d5..400f192 100644
--- a/include/linux/pinctrl/machine.h
+++ b/include/linux/pinctrl/machine.h
@@ -46,13 +46,6 @@ struct pinctrl_map {
{ .name = a, .ctrl_dev_name = b, .function = c, .dev_name = d }
/*
- * Convenience macro to map a system function onto a certain pinctrl device.
- * System functions are not assigned to a particular device.
- */
-#define PIN_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 pin control core until the system shuts down.
*/
--
1.7.5.4
pinctrl_register_mappings() already requires that every mapping table
entry have a non-NULL name field.
Logically, this makes sense too; drivers should always request a specific
named state so they know what they're getting. Relying on getting the
first mentioned state in the mapping table is error-prone, and a nasty
special case to implement, given that a given the mapping table may define
multiple states for a device.
Update a few places in the code and documentation that still allowed for
NULL name fields.
Signed-off-by: Stephen Warren <[email protected]>
---
Documentation/pinctrl.txt | 8 ++------
drivers/pinctrl/core.c | 25 ++++++++-----------------
2 files changed, 10 insertions(+), 23 deletions(-)
diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt
index ee3266b..bfe83b1 100644
--- a/Documentation/pinctrl.txt
+++ b/Documentation/pinctrl.txt
@@ -934,7 +934,7 @@ foo_probe()
/* Allocate a state holder named "state" etc */
struct pinctrl p;
- p = pinctrl_get(&device, NULL);
+ p = pinctrl_get(&device, "default");
if IS_ERR(p)
return PTR_ERR(p);
pinctrl_enable(p);
@@ -948,10 +948,6 @@ foo_remove()
pinctrl_put(state->p);
}
-If you want to grab a specific control mapping and not just the first one
-found for this device you can specify a specific mapping name, for example in
-the above example the second i2c0 setting: pinctrl_get(&device, "spi0-pos-B");
-
This get/enable/disable/put sequence can just as well be handled by bus drivers
if you don't want each and every driver to handle it and you know the
arrangement on your bus.
@@ -1003,7 +999,7 @@ Since it may be common to request the core to hog a few always-applicable
mux settings on the primary pin controller, there is a convenience macro for
this:
-PIN_MAP_PRIMARY_SYS_HOG("POWERMAP", "pinctrl-foo", "power_func")
+PIN_MAP_SYS_HOG("POWERMAP", "pinctrl-foo", "power_func")
This gives the exact same result as the above construction.
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index b6e3c35..5e30d91 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -488,8 +488,8 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev, const char *name)
int i;
struct pinctrl_map const *map;
- /* We must have dev or ID or both */
- if (!dev && !name)
+ /* We must have a state name */
+ if (WARN_ON(!name))
return ERR_PTR(-EINVAL);
if (dev)
@@ -530,23 +530,16 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev, const char *name)
pr_debug("in map, found pctldev %s to handle function %s",
dev_name(pctldev->dev), map->function);
- /*
- * If we're looking for a specific named map, this must match,
- * else we loop and look for the next.
- */
- if (name != NULL) {
- if (map->name == NULL)
- continue;
- if (strcmp(map->name, name))
- continue;
- }
+ /* State name must be the one we're looking for */
+ if (strcmp(map->name, name))
+ continue;
/*
* This is for the case where no device name is given, we
* already know that the function name matches from above
* code.
*/
- if (!map->dev_name && (name != NULL))
+ if (!map->dev_name)
found_map = true;
/* If the mapping has a device set up it must match */
@@ -570,16 +563,14 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev, const char *name)
/* We should have atleast one map, right */
if (!num_maps) {
pr_err("could not find any mux maps for device %s, ID %s\n",
- devname ? devname : "(anonymous)",
- name ? name : "(undefined)");
+ devname ? devname : "(anonymous)", name);
kfree(p);
return ERR_PTR(-EINVAL);
}
pr_debug("found %u mux maps for device %s, UD %s\n",
num_maps,
- devname ? devname : "(anonymous)",
- name ? name : "(undefined)");
+ devname ? devname : "(anonymous)", name);
/* Add the pinmux to the global list */
mutex_lock(&pinctrl_list_mutex);
--
1.7.5.4
This mostly makes debugfs files print things in the order that they
were added or acquired, which just feels a little more consistent.
Signed-off-by: Stephen Warren <[email protected]>
---
drivers/pinctrl/core.c | 8 ++++----
drivers/pinctrl/pinmux.c | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index 84a24a6..feadf1c 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -309,7 +309,7 @@ void pinctrl_add_gpio_range(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range)
{
mutex_lock(&pctldev->gpio_ranges_lock);
- list_add(&range->node, &pctldev->gpio_ranges);
+ list_add_tail(&range->node, &pctldev->gpio_ranges);
mutex_unlock(&pctldev->gpio_ranges_lock);
}
@@ -569,7 +569,7 @@ struct pinctrl *pinctrl_get(struct device *dev, const char *name)
/* Add the pinmux to the global list */
mutex_lock(&pinctrl_list_mutex);
- list_add(&p->node, &pinctrl_list);
+ list_add_tail(&p->node, &pinctrl_list);
mutex_unlock(&pinctrl_list_mutex);
return p;
@@ -749,7 +749,7 @@ static int pinctrl_hog_map(struct pinctrl_dev *pctldev,
dev_info(pctldev->dev, "hogged map %s, function %s\n", map->name,
map->function);
mutex_lock(&pctldev->pinctrl_hogs_lock);
- list_add(&hog->node, &pctldev->pinctrl_hogs);
+ list_add_tail(&hog->node, &pctldev->pinctrl_hogs);
mutex_unlock(&pctldev->pinctrl_hogs_lock);
return 0;
@@ -1197,7 +1197,7 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
pinctrl_init_device_debugfs(pctldev);
mutex_lock(&pinctrldev_list_mutex);
- list_add(&pctldev->node, &pinctrldev_list);
+ list_add_tail(&pctldev->node, &pinctrldev_list);
mutex_unlock(&pinctrldev_list_mutex);
pinctrl_hog_maps(pctldev);
return pctldev;
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c
index fe4a007..5a09cd2 100644
--- a/drivers/pinctrl/pinmux.c
+++ b/drivers/pinctrl/pinmux.c
@@ -480,7 +480,7 @@ static int pinmux_enable_muxmap(struct pinctrl_dev *pctldev,
kfree(grp);
return ret;
}
- list_add(&grp->node, &p->groups);
+ list_add_tail(&grp->node, &p->groups);
return 0;
}
--
1.7.5.4
Modify the two files so that the order of function prototypes in the
header matches the order of implementations in the .c file.
Signed-off-by: Stephen Warren <[email protected]>
---
drivers/pinctrl/pinmux.c | 56 +++++++++++++++++++++++-----------------------
drivers/pinctrl/pinmux.h | 16 ++++++------
2 files changed, 36 insertions(+), 36 deletions(-)
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c
index 24c4de1..2887897 100644
--- a/drivers/pinctrl/pinmux.c
+++ b/drivers/pinctrl/pinmux.c
@@ -40,6 +40,34 @@ struct pinmux_group {
unsigned group_selector;
};
+int pinmux_check_ops(struct pinctrl_dev *pctldev)
+{
+ const struct pinmux_ops *ops = pctldev->desc->pmxops;
+ unsigned selector = 0;
+
+ /* Check that we implement required operations */
+ if (!ops->list_functions ||
+ !ops->get_function_name ||
+ !ops->get_function_groups ||
+ !ops->enable ||
+ !ops->disable)
+ return -EINVAL;
+
+ /* Check that all functions registered have names */
+ while (ops->list_functions(pctldev, selector) >= 0) {
+ const char *fname = ops->get_function_name(pctldev,
+ selector);
+ if (!fname) {
+ pr_err("pinmux ops has no name for function%u\n",
+ selector);
+ return -EINVAL;
+ }
+ selector++;
+ }
+
+ return 0;
+}
+
/**
* pin_request() - request a single pin to be muxed in, typically for GPIO
* @pin: the pin number in the global pin space
@@ -553,34 +581,6 @@ void pinmux_disable(struct pinctrl *p)
}
}
-int pinmux_check_ops(struct pinctrl_dev *pctldev)
-{
- const struct pinmux_ops *ops = pctldev->desc->pmxops;
- unsigned selector = 0;
-
- /* Check that we implement required operations */
- if (!ops->list_functions ||
- !ops->get_function_name ||
- !ops->get_function_groups ||
- !ops->enable ||
- !ops->disable)
- return -EINVAL;
-
- /* Check that all functions registered have names */
- while (ops->list_functions(pctldev, selector) >= 0) {
- const char *fname = ops->get_function_name(pctldev,
- selector);
- if (!fname) {
- pr_err("pinmux ops has no name for function%u\n",
- selector);
- return -EINVAL;
- }
- selector++;
- }
-
- return 0;
-}
-
#ifdef CONFIG_DEBUG_FS
/* Called from pincontrol core */
diff --git a/drivers/pinctrl/pinmux.h b/drivers/pinctrl/pinmux.h
index 7680a17..84b8fe9 100644
--- a/drivers/pinctrl/pinmux.h
+++ b/drivers/pinctrl/pinmux.h
@@ -13,8 +13,6 @@
#ifdef CONFIG_PINMUX
int pinmux_check_ops(struct pinctrl_dev *pctldev);
-void pinmux_init_device_debugfs(struct dentry *devroot,
- struct pinctrl_dev *pctldev);
int pinmux_request_gpio(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned pin, unsigned gpio);
@@ -36,6 +34,8 @@ int pinmux_apply_muxmap(struct pinctrl_dev *pctldev,
void pinmux_put(struct pinctrl *p);
int pinmux_enable(struct pinctrl *p);
void pinmux_disable(struct pinctrl *p);
+void pinmux_init_device_debugfs(struct dentry *devroot,
+ struct pinctrl_dev *pctldev);
void pinmux_dbg_show(struct seq_file *s, struct pinctrl *p);
#else
@@ -45,11 +45,6 @@ static inline int pinmux_check_ops(struct pinctrl_dev *pctldev)
return 0;
}
-static inline void pinmux_init_device_debugfs(struct dentry *devroot,
- struct pinctrl_dev *pctldev)
-{
-}
-
static inline int pinmux_request_gpio(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned pin, unsigned gpio)
@@ -95,7 +90,12 @@ static inline void pinmux_disable(struct pinctrl *p)
{
}
-void pinmux_dbg_show(struct seq_file *s, struct pinctrl *p)
+static inline void pinmux_init_device_debugfs(struct dentry *devroot,
+ struct pinctrl_dev *pctldev)
+{
+}
+
+static inline void pinmux_dbg_show(struct seq_file *s, struct pinctrl *p)
{
}
--
1.7.5.4
On Mon, Feb 20, 2012 at 7:45 AM, Stephen Warren <[email protected]> wrote:
> It may be common for pinctrl_register_mappings() to be used from __init
> context, but there's no reason that additional mappings shouldn't be
> added at a later point, e.g. if loading modules that add pin controllers
> and their mapping tables.
>
> Signed-off-by: Stephen Warren <[email protected]>
OK applied.
Thanks,
Linus Walleij
On Mon, Feb 20, 2012 at 7:45 AM, Stephen Warren <[email protected]> wrote:
> This mostly makes debugfs files print things in the order that they
> were added or acquired, which just feels a little more consistent.
>
> Signed-off-by: Stephen Warren <[email protected]>
OK applied.
Thanks,
Linus Walleij
On Mon, Feb 20, 2012 at 7:45 AM, Stephen Warren <[email protected]> wrote:
> Instead of storing a single array of mapping table entries, which
> requires realloc()ing that array each time it's extended and copying
> the new data, simply store a list of pointers to the individual chunks.
> This also removes the need to copy the mapping table at all; a pointer
> is maintained to the original table, this saving memory.
>
> A macro for_each_maps() is introduced to hide the additional complexity
> of iterating over the map entries.
>
> This change will also simplify removing chunks of entries from the mapping
> table. This isn't important right now, but will be in the future, when
> mapping table entries are dynamically added when parsing them from the
> device tree, and removed when drivers no longer need to interact with
> pinctrl.
>
> Signed-off-by: Stephen Warren <[email protected]>
> ---
> v2: Fixed kzalloc size parameter in pinctrl_register_mappings(),
> ? ?add pr_error on kzalloc() failure, keep pinctrl_get() docs with
> ? ?pinctrl_get() not pinctrl_get_locked(), make pinctrl_get_locked()
> ? ?static, use list_add_tail instead of list_add, continue to duplicate
> ? ?mapping table, don't remove __initdata from u300 mapping table.
Brilliant, applied.
Also tested on U300 up to this point, everything works just fine.
Thanks,
Linus Walleij
On Mon, Feb 20, 2012 at 7:45 AM, Stephen Warren <[email protected]> wrote:
> When pins are requested/acquired/got, some device becomes the owner of
> their mux setting. At this point, it isn't certain which mux function
> will be selected for the pin, since this may vary between each of the
> device's states in the pinctrl mapping table. As such, we should record
> the owning device, not what we think the initial mux setting will be,
> when requesting pins.
>
> This doesn't make a lot of difference right now since pinctrl_get gets
> only one single device/state combination, but this will make a difference
> when pinctrl_get gets all states, and pinctrl_select_state can switch
> between states.
>
> Signed-off-by: Stephen Warren <[email protected]>
Mostly a rename then, OK...
> @@ -66,19 +65,14 @@ static int pin_request(struct pinctrl_dev *pctldev,
> ? ? ? ? ? ? ? ?goto out;
> ? ? ? ?}
>
> - ? ? ? if (!function) {
> - ? ? ? ? ? ? ? dev_err(pctldev->dev, "no function name given\n");
> - ? ? ? ? ? ? ? return -EINVAL;
> - ? ? ? }
> -
Why should it be allowed to have a NULL owner? There is a
debug print involving it above but ... maybe this is over-cautious?
Yours,
Linus Walleij
On Mon, Feb 20, 2012 at 7:45 AM, Stephen Warren <[email protected]> wrote:
> Modify the two files so that the order of function prototypes in the
> header matches the order of implementations in the .c file.
>
> Signed-off-by: Stephen Warren <[email protected]>
OK applied.
Thanks,
Linus Walleij
On Mon, Feb 20, 2012 at 7:45 AM, Stephen Warren <[email protected]> wrote:
> Modify the two files so that the order of function prototypes in the
> header matches the order of implementations in the .c file.
>
> Don't prototype a couple of internal functions.
>
> Signed-off-by: Stephen Warren <[email protected]>
OK applied.
Thanks,
Linus Walleij
On Mon, Feb 20, 2012 at 7:45 AM, Stephen Warren <[email protected]> wrote:
> * Make all functions internal to core.c static. Remove any of these from
> ?core.h.
> * Add any missing EXPORT_SYMBOL_GPL().
>
> Signed-off-by: Stephen Warren <[email protected]>
OK applied.
Thanks,
Linus Walleij
On Mon, Feb 20, 2012 at 7:45 AM, Stephen Warren <[email protected]> wrote:
> pinctrl_register_mappings() already requires that every mapping table
> entry have a non-NULL name field.
>
> Logically, this makes sense too; drivers should always request a specific
> named state so they know what they're getting. Relying on getting the
> first mentioned state in the mapping table is error-prone, and a nasty
> special case to implement, given that a given the mapping table may define
> multiple states for a device.
>
> Update a few places in the code and documentation that still allowed for
> NULL name fields.
>
> Signed-off-by: Stephen Warren <[email protected]>
This causes a regression on U300 and most certainly on the Sirf Prima II
as well. The U300 can be fixed up as per below:
diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c
index bb1034f..66555d7 100644
--- a/arch/arm/mach-u300/core.c
+++ b/arch/arm/mach-u300/core.c
@@ -1645,7 +1645,7 @@ static int __init u300_pinctrl_fetch(void)
struct pinctrl *p;
int ret;
- p = pinctrl_get(u300_mux_hogs[i].dev, NULL);
+ p = pinctrl_get(u300_mux_hogs[i].dev, u300_mux_hogs[i].name);
if (IS_ERR(p)) {
pr_err("u300: could not get pinmux hog %s\n",
u300_mux_hogs[i].name);
The drivers/tty/serial/sirfsoc_uart.c asks for it's UART pinctrl like
this:
sirfport->p = pinctrl_get(&pdev->dev, NULL);
I don't know quite what to encode in there, if "deafult" is sensible
we might just
#define PIN_MAP_NAME_DEFAULT "default"
In <linux/pinctrl/consumer.h> and <linux/pinctrl/machine.h> alike,
maybe in some <linux/pinctrl/mapnames.h> that both of these
include?
the have the driver ask for:
sirfport->p = pinctrl_get(&pdev->dev, PIN_MAP_NAME_DEFAULT);
(Similar changes can be done for U300, naming all its map
"default".)
Yours,
Linus Walleij
On Mon, Feb 20, 2012 at 7:45 AM, Stephen Warren <[email protected]> wrote:
> Hog entries are mapping table entries with .ctrl_dev_name == .dev_name.
> All other mapping table entries need .dev_name set so that they will
> match some pinctrl_get() call. All extant PIN_MAP*() macros set
> .dev_name.
>
> So, there is no reason to allow mapping table entries without .dev_name
> set. Update the code and documentation to disallow this.
>
> Signed-off-by: Stephen Warren <[email protected]>
OK
Acked-by: Linus Walleij <[email protected]>
I would have applied it if it wasn't that I had some questions
on earlier patches that I didn't apply so it conflicts.
Yours,
Linus Walleij
OK I got to patch 10 tonight, so I applied these to for-next
and pushed:
3a4de0b pinctrl: core.c/h cleanups
144e2bb pinctrl: Re-order pinconf.[ch] to match each-other
dd36982b pinctrl: Re-order pinmux.[ch] to match each-other
7dbf763 pinctrl: Store mapping table as a list of chunks
78917f6 pinctrl: use list_add_tail instead of list_add
9c8484d pinctrl: pinctrl_register_mappings() shouldn't be __init
Will continue reviewing tomorrow.
Thanks,
Linus Walleij
On Mon, Feb 20, 2012 at 2:45 PM, Stephen Warren <[email protected]> wrote:
> pinctrl_register_mappings() already requires that every mapping table
> entry have a non-NULL name field.
>
> Logically, this makes sense too; drivers should always request a specific
> named state so they know what they're getting. Relying on getting the
Hmm? It makes me a little confused.
IIRC we allow the driver to request NULL map name in the linaro
connect discussion.
For those devices they do not want to support multi states, they
really don't want to care about the state name.
The original way is convenient for such a case.
> first mentioned state in the mapping table is error-prone, and a nasty
> special case to implement, given that a given the mapping table may define
> multiple states for a device.
>
User should know this constraint.
> diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
> index b6e3c35..5e30d91 100644
> --- a/drivers/pinctrl/core.c
> +++ b/drivers/pinctrl/core.c
> @@ -488,8 +488,8 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev, const char *name)
> ? ? ? ?int i;
> ? ? ? ?struct pinctrl_map const *map;
>
> - ? ? ? /* We must have dev or ID or both */
> - ? ? ? if (!dev && !name)
> + ? ? ? /* We must have a state name */
> + ? ? ? if (WARN_ON(!name))
> ? ? ? ? ? ? ? ?return ERR_PTR(-EINVAL);
>
We're already using the pinctrl device name for hog map.
So should it be something like:
if (WARN_ON(!dev) || WARN_ON(!name))
> ? ? ? ?if (dev)
> @@ -530,23 +530,16 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev, const char *name)
> ? ? ? ? ? ? ? ?pr_debug("in map, found pctldev %s to handle function %s",
> ? ? ? ? ? ? ? ? ? ? ? ? dev_name(pctldev->dev), map->function);
>
> - ? ? ? ? ? ? ? /*
> - ? ? ? ? ? ? ? ?* If we're looking for a specific named map, this must match,
> - ? ? ? ? ? ? ? ?* else we loop and look for the next.
> - ? ? ? ? ? ? ? ?*/
> - ? ? ? ? ? ? ? if (name != NULL) {
> - ? ? ? ? ? ? ? ? ? ? ? if (map->name == NULL)
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? continue;
> - ? ? ? ? ? ? ? ? ? ? ? if (strcmp(map->name, name))
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? continue;
> - ? ? ? ? ? ? ? }
> + ? ? ? ? ? ? ? /* State name must be the one we're looking for */
> + ? ? ? ? ? ? ? if (strcmp(map->name, name))
> + ? ? ? ? ? ? ? ? ? ? ? continue;
>
> ? ? ? ? ? ? ? ?/*
> ? ? ? ? ? ? ? ? * This is for the case where no device name is given, we
> ? ? ? ? ? ? ? ? * already know that the function name matches from above
> ? ? ? ? ? ? ? ? * code.
> ? ? ? ? ? ? ? ? */
> - ? ? ? ? ? ? ? if (!map->dev_name && (name != NULL))
> + ? ? ? ? ? ? ? if (!map->dev_name)
> ? ? ? ? ? ? ? ? ? ? ? ?found_map = true;
Do we still need this?
Is there still a case the dev_name can be NULL?
>
> ? ? ? ? ? ? ? ?/* If the mapping has a device set up it must match */
> @@ -570,16 +563,14 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev, const char *name)
> ? ? ? ?/* We should have atleast one map, right */
> ? ? ? ?if (!num_maps) {
> ? ? ? ? ? ? ? ?pr_err("could not find any mux maps for device %s, ID %s\n",
> - ? ? ? ? ? ? ? ? ? ? ?devname ? devname : "(anonymous)",
> - ? ? ? ? ? ? ? ? ? ? ?name ? name : "(undefined)");
> + ? ? ? ? ? ? ? ? ? ? ?devname ? devname : "(anonymous)", name);
> ? ? ? ? ? ? ? ?kfree(p);
> ? ? ? ? ? ? ? ?return ERR_PTR(-EINVAL);
> ? ? ? ?}
>
> ? ? ? ?pr_debug("found %u mux maps for device %s, UD %s\n",
> ? ? ? ? ? ? ? ? num_maps,
> - ? ? ? ? ? ? ? ?devname ? devname : "(anonymous)",
> - ? ? ? ? ? ? ? ?name ? name : "(undefined)");
> + ? ? ? ? ? ? ? ?devname ? devname : "(anonymous)", name);
>
> ? ? ? ?/* Add the pinmux to the global list */
> ? ? ? ?mutex_lock(&pinctrl_list_mutex);
> --
> 1.7.5.4
>
Regards
Dong Aisheng
On Tue, Feb 21, 2012 at 5:42 AM, Linus Walleij <[email protected]> wrote:
> On Mon, Feb 20, 2012 at 7:45 AM, Stephen Warren <[email protected]> wrote:
>
>> pinctrl_register_mappings() already requires that every mapping table
>> entry have a non-NULL name field.
>>
>> Logically, this makes sense too; drivers should always request a specific
>> named state so they know what they're getting. Relying on getting the
>> first mentioned state in the mapping table is error-prone, and a nasty
>> special case to implement, given that a given the mapping table may define
>> multiple states for a device.
>>
>> Update a few places in the code and documentation that still allowed for
>> NULL name fields.
>>
>> Signed-off-by: Stephen Warren <[email protected]>
>
> This causes a regression on U300 and most certainly on the Sirf Prima II
> as well. The U300 can be fixed up as per below:
>
> diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c
> index bb1034f..66555d7 100644
> --- a/arch/arm/mach-u300/core.c
> +++ b/arch/arm/mach-u300/core.c
> @@ -1645,7 +1645,7 @@ static int __init u300_pinctrl_fetch(void)
> ? ? ? ? ? ? ? ?struct pinctrl *p;
> ? ? ? ? ? ? ? ?int ret;
>
> - ? ? ? ? ? ? ? p = pinctrl_get(u300_mux_hogs[i].dev, NULL);
> + ? ? ? ? ? ? ? p = pinctrl_get(u300_mux_hogs[i].dev, u300_mux_hogs[i].name);
> ? ? ? ? ? ? ? ?if (IS_ERR(p)) {
> ? ? ? ? ? ? ? ? ? ? ? ?pr_err("u300: could not get pinmux hog %s\n",
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? u300_mux_hogs[i].name);
>
>
> The drivers/tty/serial/sirfsoc_uart.c asks for it's UART pinctrl like
> this:
>
> sirfport->p = pinctrl_get(&pdev->dev, NULL);
>
> I don't know quite what to encode in there, if "deafult" is sensible
> we might just
>
> #define PIN_MAP_NAME_DEFAULT "default"
> In <linux/pinctrl/consumer.h> and <linux/pinctrl/machine.h> alike,
> maybe in some <linux/pinctrl/mapnames.h> that both of these
> include?
>
I feel a little strange to put such thing in common code.
Personally i still like the original way you did.
> the have the driver ask for:
>
> sirfport->p = pinctrl_get(&pdev->dev, PIN_MAP_NAME_DEFAULT);
>
> (Similar changes can be done for U300, naming all its map
> "default".)
>
Regards
Dong Aisheng
On Tue, Feb 21, 2012 at 2:09 PM, Dong Aisheng <[email protected]> wrote:
> On Tue, Feb 21, 2012 at 5:42 AM, Linus Walleij <[email protected]> wrote:
>> On Mon, Feb 20, 2012 at 7:45 AM, Stephen Warren <[email protected]> wrote:
>>
>>> pinctrl_register_mappings() already requires that every mapping table
>>> entry have a non-NULL name field.
>>>
>>> Logically, this makes sense too; drivers should always request a specific
>>> named state so they know what they're getting. Relying on getting the
>>> first mentioned state in the mapping table is error-prone, and a nasty
>>> special case to implement, given that a given the mapping table may define
>>> multiple states for a device.
>>>
>>> Update a few places in the code and documentation that still allowed for
>>> NULL name fields.
>>>
>>> Signed-off-by: Stephen Warren <[email protected]>
>>
>> This causes a regression on U300 and most certainly on the Sirf Prima II
>> as well. The U300 can be fixed up as per below:
>>
>> diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c
>> index bb1034f..66555d7 100644
>> --- a/arch/arm/mach-u300/core.c
>> +++ b/arch/arm/mach-u300/core.c
>> @@ -1645,7 +1645,7 @@ static int __init u300_pinctrl_fetch(void)
>> ? ? ? ? ? ? ? ?struct pinctrl *p;
>> ? ? ? ? ? ? ? ?int ret;
>>
>> - ? ? ? ? ? ? ? p = pinctrl_get(u300_mux_hogs[i].dev, NULL);
>> + ? ? ? ? ? ? ? p = pinctrl_get(u300_mux_hogs[i].dev, u300_mux_hogs[i].name);
>> ? ? ? ? ? ? ? ?if (IS_ERR(p)) {
>> ? ? ? ? ? ? ? ? ? ? ? ?pr_err("u300: could not get pinmux hog %s\n",
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? u300_mux_hogs[i].name);
>>
>>
>> The drivers/tty/serial/sirfsoc_uart.c asks for it's UART pinctrl like
>> this:
>>
>> sirfport->p = pinctrl_get(&pdev->dev, NULL);
>>
>> I don't know quite what to encode in there, if "deafult" is sensible
>> we might just
>>
>> #define PIN_MAP_NAME_DEFAULT "default"
>> In <linux/pinctrl/consumer.h> and <linux/pinctrl/machine.h> alike,
>> maybe in some <linux/pinctrl/mapnames.h> that both of these
>> include?
>>
> I feel a little strange to put such thing in common code.
> Personally i still like the original way you did.
I think with this patch alone it doesn't make much sense
to enforce the request to specify a certain map, it only
appears further ahead as we start to support states.
Let's look through the entire patch series so as to get
the bigger picture.
Yours,
Linus Walleij
On Mon, Feb 20, 2012 at 7:45 AM, Stephen Warren <[email protected]> wrote:
> These are already disallowed. Clean up some code that doesn't assume this.
>
> Signed-off-by: Stephen Warren <[email protected]>
Thanks, applied!
Yours,
Linus Walleij
On Mon, Feb 20, 2012 at 7:45 AM, Stephen Warren <[email protected]> wrote:
> This may be perfectly legitimate. An IP block may get re-used
> across SoCs. Not all of those SoCs may need pinmux settings for the
> IP block, e.g. if one SoC dedicates pins to that function but
> another doesn't. The driver won't know this, and will always
> attempt to set up the pinmux. The mapping table defines whether any
> HW programming is actually needed.
>
> Signed-off-by: Stephen Warren <[email protected]>
This is equivalent to providing dummy pincontrollers as was on my
TODO for a while admittedly.
For consistency with regulators it would maybe be better to have
optional dummy pin controllers but after thinking a bit about it
I think this is more helpful, so I applied it anyway.
However I would invite more opinions...
Yours,
Linus Walleij
On Mon, Feb 20, 2012 at 7:45 AM, Stephen Warren <[email protected]> wrote:
> This is a serious error, and the pin control system will not function
> correctly if it ends up not programing the mapping table entries into
> the HW. Instead of just ignoring this, error out.
>
> Signed-off-by: Stephen Warren <[email protected]>
Thanks applied, this came to bite me today so I see the value
of being strict here.
> + ? ? ? ? ? ? ? ? ? ? ? /* Eventually, this should trigger deferred probe */
> + ? ? ? ? ? ? ? ? ? ? ? return -ENODEV;
I changed this to ERR_PTR(-ENODEV) in my codebase as
it returns a pointer.
Yours,
Linus Walleij
Linus Walleij wrote at Monday, February 20, 2012 2:15 PM:
> On Mon, Feb 20, 2012 at 7:45 AM, Stephen Warren <[email protected]> wrote:
>
> > When pins are requested/acquired/got, some device becomes the owner of
> > their mux setting. At this point, it isn't certain which mux function
> > will be selected for the pin, since this may vary between each of the
> > device's states in the pinctrl mapping table. As such, we should record
> > the owning device, not what we think the initial mux setting will be,
> > when requesting pins.
> >
> > This doesn't make a lot of difference right now since pinctrl_get gets
> > only one single device/state combination, but this will make a difference
> > when pinctrl_get gets all states, and pinctrl_select_state can switch
> > between states.
> >
> > Signed-off-by: Stephen Warren <[email protected]>
>
> Mostly a rename then, OK...
>
> > @@ -66,19 +65,14 @@ static int pin_request(struct pinctrl_dev *pctldev,
> > ? ? ? ? ? ? ? ?goto out;
> > ? ? ? ?}
> >
> > - ? ? ? if (!function) {
> > - ? ? ? ? ? ? ? dev_err(pctldev->dev, "no function name given\n");
> > - ? ? ? ? ? ? ? return -EINVAL;
> > - ? ? ? }
> > -
>
> Why should it be allowed to have a NULL owner? There is a
> debug print involving it above but ... maybe this is over-cautious?
My reasoning was that this is an internal function, so this isn't a user-
supplied parameter we need to be paranoid about checking, and the places
that call this function internally "obviously" don't pass NULL owner.
Well, I suppose one place relies on the fact we checked elsewhere that
map->dev_name != NULL.
Still, I can see a defensive programming argument for keeping that check,
although I suspect if we apply that argument we should probably check a
lot more things too throughout the code?
--
nvpublic
Dong Aisheng wrote at Tuesday, February 21, 2012 6:08 AM:
> On Mon, Feb 20, 2012 at 2:45 PM, Stephen Warren <[email protected]> wrote:
> > pinctrl_register_mappings() already requires that every mapping table
> > entry have a non-NULL name field.
> >
> > Logically, this makes sense too; drivers should always request a specific
> > named state so they know what they're getting. Relying on getting the
>
> Hmm? It makes me a little confused.
> IIRC we allow the driver to request NULL map name in the linaro
> connect discussion.
> For those devices they do not want to support multi states, they
> really don't want to care about the state name.
> The original way is convenient for such a case.
With device tree, every state is always going to have /some/ name; the
binding we discussed didn't include any way to specify "no name" or
"default name" or "default state", so this will keeps things a little
more consistent.
I possibly could be persuaded to allow NULL state names in the mapping
table. However, if so, I think they should work a little differently to
the code currently in pinctrl: Right now, a NULL parameter to pinmux_get()
allows matching against /any/ state name in the table. If we changed this
to only allow matching against mapping table with a NULL name, that might
be OK, since it'd be very explicit what it matched. But, as I mentione
above, migrating such a driver to device tree would require changing this
so I'm not inclined to like that solution without strong requirements.
In other words, what we have right now is something like:
if name:
match = !strcmp(name, map->name)
else:
match = true
If we continue to allow NULL names, I think we should change that to:
if name:
match = map->name && !strcmp(name, map->name)
else:
match = !map->name
> > diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
> > index b6e3c35..5e30d91 100644
> > --- a/drivers/pinctrl/core.c
> > +++ b/drivers/pinctrl/core.c
> > @@ -488,8 +488,8 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev, const char *name)
> > ? ? ? ?int i;
> > ? ? ? ?struct pinctrl_map const *map;
> >
> > - ? ? ? /* We must have dev or ID or both */
> > - ? ? ? if (!dev && !name)
> > + ? ? ? /* We must have a state name */
> > + ? ? ? if (WARN_ON(!name))
> > ? ? ? ? ? ? ? ?return ERR_PTR(-EINVAL);
>
> We're already using the pinctrl device name for hog map.
> So should it be something like:
> if (WARN_ON(!dev) || WARN_ON(!name))
That's only true starting with the next patch in this series, which does
modify the code roughly as you described.
--
nvpublic
Linus Walleij wrote at Monday, February 20, 2012 2:42 PM:
> On Mon, Feb 20, 2012 at 7:45 AM, Stephen Warren <[email protected]> wrote:
>
> > pinctrl_register_mappings() already requires that every mapping table
> > entry have a non-NULL name field.
> >
> > Logically, this makes sense too; drivers should always request a specific
> > named state so they know what they're getting. Relying on getting the
> > first mentioned state in the mapping table is error-prone, and a nasty
> > special case to implement, given that a given the mapping table may define
> > multiple states for a device.
> >
> > Update a few places in the code and documentation that still allowed for
> > NULL name fields.
> >
> > Signed-off-by: Stephen Warren <[email protected]>
>
> This causes a regression on U300 and most certainly on the Sirf Prima II
> as well. The U300 can be fixed up as per below:
Oh good point. I'd remembered to update those in later patches, but not
this one...
> diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c
> index bb1034f..66555d7 100644
> --- a/arch/arm/mach-u300/core.c
> +++ b/arch/arm/mach-u300/core.c
> @@ -1645,7 +1645,7 @@ static int __init u300_pinctrl_fetch(void)
> struct pinctrl *p;
> int ret;
>
> - p = pinctrl_get(u300_mux_hogs[i].dev, NULL);
> + p = pinctrl_get(u300_mux_hogs[i].dev, u300_mux_hogs[i].name);
> if (IS_ERR(p)) {
> pr_err("u300: could not get pinmux hog %s\n",
> u300_mux_hogs[i].name);
I don't think that works as-is; currently, the names in the U300 map table
Are MMCSD, SPI, UART0, whereas the names in u300_mux_hogs[] are mmc0, spi0,
uart0. I can easily fix up the u300_mux_hogs[] in the same patch though.
> The drivers/tty/serial/sirfsoc_uart.c asks for it's UART pinctrl like
> this:
>
> sirfport->p = pinctrl_get(&pdev->dev, NULL);
>
> I don't know quite what to encode in there, if "default" is sensible
"default" seems reasonable to me.
I couldn't find any mapping table defined for Sirf Prima II; is there
one checked in anywhere?
> we might just
>
> #define PIN_MAP_NAME_DEFAULT "default"
> In <linux/pinctrl/consumer.h> and <linux/pinctrl/machine.h> alike,
> maybe in some <linux/pinctrl/mapnames.h> that both of these
> include?
>
> the have the driver ask for:
>
> sirfport->p = pinctrl_get(&pdev->dev, PIN_MAP_NAME_DEFAULT);
>
> (Similar changes can be done for U300, naming all its map
> "default".)
I guess we could just modify pinmux_get() such that if NULL is passed as
the state name, it uses "default" instead internally. The disadvantage I
see here is that someone reading the client driver and writing the mapping
table then has to know that pinmux_get() does that internally, rather than
it being obvious right in the client driver code.
--
nvpublic
Linus Walleij wrote at Tuesday, February 21, 2012 6:59 AM:
> On Mon, Feb 20, 2012 at 7:45 AM, Stephen Warren <[email protected]> wrote:
>
> > This is a serious error, and the pin control system will not function
> > correctly if it ends up not programing the mapping table entries into
> > the HW. Instead of just ignoring this, error out.
> >
> > Signed-off-by: Stephen Warren <[email protected]>
>
> Thanks applied, this came to bite me today so I see the value
> of being strict here.
>
> > + ? ? ? ? ? ? ? ? ? ? ? /* Eventually, this should trigger deferred probe */
> > + ? ? ? ? ? ? ? ? ? ? ? return -ENODEV;
>
> I changed this to ERR_PTR(-ENODEV) in my codebase as
> it returns a pointer.
Thanks. I thought I'd fixed that up after compiling each patch individually,
but I guess I missed one:-(
--
nvpublic
On Tue, Feb 21, 2012 at 02:51:55PM +0100, Linus Walleij wrote:
> On Mon, Feb 20, 2012 at 7:45 AM, Stephen Warren <[email protected]> wrote:
>
> > This may be perfectly legitimate. An IP block may get re-used
> > across SoCs. Not all of those SoCs may need pinmux settings for the
> > IP block, e.g. if one SoC dedicates pins to that function but
> > another doesn't. The driver won't know this, and will always
> > attempt to set up the pinmux. The mapping table defines whether any
> > HW programming is actually needed.
> >
> > Signed-off-by: Stephen Warren <[email protected]>
>
> This is equivalent to providing dummy pincontrollers as was on my
> TODO for a while admittedly.
>
> For consistency with regulators it would maybe be better to have
> optional dummy pin controllers but after thinking a bit about it
> I think this is more helpful, so I applied it anyway.
>
> However I would invite more opinions...
>
I do not have an opinion on how we do it, and my opinion is just we
need to have it. So,
Acked-by: Shawn Guo <[email protected]>
--
Regards,
Shawn
On Tue, Feb 21, 2012 at 09:38:47AM -0800, Stephen Warren wrote:
> Dong Aisheng wrote at Tuesday, February 21, 2012 6:08 AM:
> > On Mon, Feb 20, 2012 at 2:45 PM, Stephen Warren <[email protected]> wrote:
> > > pinctrl_register_mappings() already requires that every mapping table
> > > entry have a non-NULL name field.
> > >
> > > Logically, this makes sense too; drivers should always request a specific
> > > named state so they know what they're getting. Relying on getting the
> >
> > Hmm? It makes me a little confused.
> > IIRC we allow the driver to request NULL map name in the linaro
> > connect discussion.
> > For those devices they do not want to support multi states, they
> > really don't want to care about the state name.
> > The original way is convenient for such a case.
>
> With device tree, every state is always going to have /some/ name; the
I remember the discussion is that pinctrl-name is optional and map name
is always specified by pinctrl-name or automatically generated by the id
of pinctrl property (e.g. for pinctrl-0, 0 is the name)
However user may not want to care about it although there's a name.
BTW my above comment may not right since i still have not read all you patches
in the series and do not know if any difference on your implementation with
the original proposal i will continue to read your patches.
> binding we discussed didn't include any way to specify "no name" or
> "default name" or "default state", so this will keeps things a little
> more consistent.
>
> I possibly could be persuaded to allow NULL state names in the mapping
> table. However, if so, I think they should work a little differently to
> the code currently in pinctrl: Right now, a NULL parameter to pinmux_get()
> allows matching against /any/ state name in the table. If we changed this
Yes it's /any/ state but it's always the first state.
> to only allow matching against mapping table with a NULL name, that might
> be OK, since it'd be very explicit what it matched. But, as I mentione
If that how about many states with NULL name?
> above, migrating such a driver to device tree would require changing this
I can see many changes, it looks just as the same as before (using first
state as default state), did i understand right?
> so I'm not inclined to like that solution without strong requirements.
>
> In other words, what we have right now is something like:
>
> if name:
> match = !strcmp(name, map->name)
> else:
> match = true
>
> If we continue to allow NULL names, I think we should change that to:
>
> if name:
> match = map->name && !strcmp(name, map->name)
> else:
> match = !map->name
As above many states name may be NULL.
So here it becomes the first NULL name state.
Regards
Dong Aisheng
On Tue, Feb 21, 2012 at 6:46 PM, Stephen Warren <[email protected]> wrote:
> I guess we could just modify pinmux_get() such that if NULL is passed as
> the state name, it uses "default" instead internally. The disadvantage I
> see here is that someone reading the client driver and writing the mapping
> table then has to know that pinmux_get() does that internally, rather than
> it being obvious right in the client driver code.
I would prefer this solution, it has the upside of not needing to touch
the sirf driver.
And please #define the string somewhere instead of open-coding
"default", it's too errorprone IMO.
Thanks,
Linus Walleij
On Tue, Feb 21, 2012 at 6:23 PM, Stephen Warren <[email protected]> wrote:
> Linus Walleij wrote at Monday, February 20, 2012 2:15 PM:
>> >
>> > - ? ? ? if (!function) {
>> > - ? ? ? ? ? ? ? dev_err(pctldev->dev, "no function name given\n");
>> > - ? ? ? ? ? ? ? return -EINVAL;
>> > - ? ? ? }
>> > -
>>
>> Why should it be allowed to have a NULL owner? There is a
>> debug print involving it above but ... maybe this is over-cautious?
>
> My reasoning was that this is an internal function, so this isn't a user-
> supplied parameter we need to be paranoid about checking, and the places
> that call this function internally "obviously" don't pass NULL owner.
> Well, I suppose one place relies on the fact we checked elsewhere that
> map->dev_name != NULL.
>
> Still, I can see a defensive programming argument for keeping that check,
> although I suspect if we apply that argument we should probably check a
> lot more things too throughout the code?
Bah whatever, no big deal.
Patch applied!
Thanks,
Linus Walleij
On Mon, Feb 20, 2012 at 7:45 AM, Stephen Warren <[email protected]> wrote:
> e.g. dev_err instead of pr_err prints messages in a slightly more
> standardized format.
Acked-by: Linus Walleij <[email protected]>
Fine with me but I couldn't apply it due to too many conflicts due to
the unapplied patch for handling NULL regulators that we haven't
ironed out yet, so will need some rebasing...
Thanks,
Linus Walleij
On Mon, Feb 20, 2012 at 7:45 AM, Stephen Warren <[email protected]> wrote:
> This hopefully makes it harder to take the sizeof the wrong type.
>
> Signed-off-by: Stephen Warren <[email protected]>
Acked-by: Linus Walleij <[email protected]>
Would apply it if it wasn't for the conflicts...
Thanks,
Linus Walleij
On Tue, Feb 21, 2012 at 09:46:01AM -0800, Stephen Warren wrote:
....
> > we might just
> >
> > #define PIN_MAP_NAME_DEFAULT "default"
> > In <linux/pinctrl/consumer.h> and <linux/pinctrl/machine.h> alike,
> > maybe in some <linux/pinctrl/mapnames.h> that both of these
> > include?
> >
> > the have the driver ask for:
> >
> > sirfport->p = pinctrl_get(&pdev->dev, PIN_MAP_NAME_DEFAULT);
> >
> > (Similar changes can be done for U300, naming all its map
> > "default".)
>
> I guess we could just modify pinmux_get() such that if NULL is passed as
> the state name, it uses "default" instead internally. The disadvantage I
> see here is that someone reading the client driver and writing the mapping
> table then has to know that pinmux_get() does that internally, rather than
> it being obvious right in the client driver code.
>
It looks like a way out.
The left problem seems to be that we may force the mapping table writer to
specify "default" name for map at least.
Is there any way to avoid it?
I just think it may be better if we do not have such restriction.
Regards
Dong Aisheng
On Sun, Feb 19, 2012 at 11:45:49PM -0700, Stephen Warren wrote:
> Hog entries are mapping table entries with .ctrl_dev_name == .dev_name.
> All other mapping table entries need .dev_name set so that they will
> match some pinctrl_get() call. All extant PIN_MAP*() macros set
> .dev_name.
>
> So, there is no reason to allow mapping table entries without .dev_name
> set. Update the code and documentation to disallow this.
>
> Signed-off-by: Stephen Warren <[email protected]>
> ---
Except code derived from last patch that not allow the map name to be NULL
for pinctrl_get since it seems still not determined, for this patch itself:
Acked-by: Dong Aisheng <[email protected]>
Regards
Dong Aisheng
On Sun, Feb 19, 2012 at 11:45:50PM -0700, Stephen Warren wrote:
> These are already disallowed. Clean up some code that doesn't assume this.
>
> Signed-off-by: Stephen Warren <[email protected]>
> ---
> drivers/pinctrl/core.c | 3 +--
> 1 files changed, 1 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
> index 331ffb6..37dfac7 100644
> --- a/drivers/pinctrl/core.c
> +++ b/drivers/pinctrl/core.c
> @@ -770,8 +770,7 @@ static int pinctrl_hog_maps(struct pinctrl_dev *pctldev)
>
> mutex_lock(&pinctrl_maps_mutex);
> for_each_maps(maps_node, i, map) {
> - if (map->ctrl_dev_name &&
> - !strcmp(map->ctrl_dev_name, devname) &&
> + if (!strcmp(map->ctrl_dev_name, devname) &&
> !strcmp(map->dev_name, devname)) {
> /* OK time to hog! */
> ret = pinctrl_hog_map(pctldev, map);
> --
> 1.7.5.4
>
Acked-by: Dong Aisheng <[email protected]>
Regards
Dong Aisheng
On Tue, Feb 21, 2012 at 02:51:55PM +0100, Linus Walleij wrote:
> On Mon, Feb 20, 2012 at 7:45 AM, Stephen Warren <[email protected]> wrote:
>
> > This may be perfectly legitimate. An IP block may get re-used
> > across SoCs. Not all of those SoCs may need pinmux settings for the
> > IP block, e.g. if one SoC dedicates pins to that function but
> > another doesn't. The driver won't know this, and will always
> > attempt to set up the pinmux. The mapping table defines whether any
> > HW programming is actually needed.
> >
> > Signed-off-by: Stephen Warren <[email protected]>
>
> This is equivalent to providing dummy pincontrollers as was on my
> TODO for a while admittedly.
>
> For consistency with regulators it would maybe be better to have
> optional dummy pin controllers but after thinking a bit about it
> I think this is more helpful, so I applied it anyway.
>
> However I would invite more opinions...
>
I'm afraid this is a little error-prone, that means even we specifed
the wrong map name or state name, the pinctrl_get still does not get
failed and it is a little different as what we want in this patch.
Regards
Dong Aisheng
On Sun, Feb 19, 2012 at 11:45:52PM -0700, Stephen Warren wrote:
> e.g. dev_err instead of pr_err prints messages in a slightly more
> standardized format.
>
> Also, add a few more error messages to track down errors.
>
> Also, some small cleanups of messages.
>
> Signed-off-by: Stephen Warren <[email protected]>
> ---
Acked-by: Dong Aisheng <[email protected]>
Regards
Dong Aisheng
On Sun, Feb 19, 2012 at 11:45:54PM -0700, Stephen Warren wrote:
> This hopefully makes it harder to take the sizeof the wrong type.
>
> Signed-off-by: Stephen Warren <[email protected]>
Acked-by: Dong Aisheng <[email protected]>
Regards
Dong Aisheng
On Mon, Feb 20, 2012 at 7:45 AM, Stephen Warren <[email protected]> wrote:
> This change separates two aspects of struct pinctrl:
>
> a) The data representation of the parsed mapping table, into:
>
> ? 1) The top-level struct pinctrl object, a single entity returned
> ? ? ?by pinctrl_get().
>
> ? 2) The parsed version of each mapping table entry, struct
> ? ? ?pinctrl_setting, of which there is one per mapping table entry.
>
> b) The code that handles this; the code for (1) above is in core.c, and
> ? the code to parse/execute each entry in (2) above is in pinmux.c, while
> ? the iteration over multiple settings is lifted to core.c.
>
> This will allow the following future changes:
>
> 1) pinctrl_get() API rework, so that struct pinctrl represents all states
> ? for the device, and the device can select between them without calling
> ? put()/get() again.
>
> 2) To support that, a struct pinctrl_state object will be inserted into
> ? the data model between the struct pinctrl and struct pinctrl_setting.
>
> 3) The mapping table will be extended to allow specification of pin config
> ? settings too. To support this, struct pinctrl_setting will be enhanced
> ? to store either mux settings or config settings, and functions will be
> ? added to pinconf.c to parse/execute pin configuration settings.
>
> Signed-off-by: Stephen Warren <[email protected]>
This is elegant and exactly what we want to do.
Please rebase on top of well, whatever we agree upon for
handling the get(NULL) case, and we're set to merge this
too.
Acked-by: Linus Walleij <[email protected]>
Thanks,
Linus Walleij
On Mon, Feb 20, 2012 at 7:45 AM, Stephen Warren <[email protected]> wrote:
> Multiple mapping table entries could reference the same pin, and hence
> "own" it. This would be unusual now that pinctrl_get() represents a single
> state for a client device, but in the future when it represents all known
> states for a device, this is quite likely. Implement reference counting
> for pin ownership to handle this.
>
> Signed-off-by: Stephen Warren <[email protected]>
Seems like a good straight-forward way to solve this.
> diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h
> index 1290995..64ae1b8 100644
> --- a/drivers/pinctrl/core.h
> +++ b/drivers/pinctrl/core.h
> @@ -92,6 +92,7 @@ struct pin_desc {
> ? ? ? ?bool dynamic_name;
> ? ? ? ?/* These fields only added when supporting pinmux drivers */
> ?#ifdef CONFIG_PINMUX
> + ? ? ? unsigned usecount;
kerneldoc for this? Preferably verbose...
Thanks,
Linus Walleij
Dong Aisheng wrote at Tuesday, February 21, 2012 11:57 PM:
> On Tue, Feb 21, 2012 at 02:51:55PM +0100, Linus Walleij wrote:
> > On Mon, Feb 20, 2012 at 7:45 AM, Stephen Warren <[email protected]> wrote:
> >
> > > This may be perfectly legitimate. An IP block may get re-used
> > > across SoCs. Not all of those SoCs may need pinmux settings for the
> > > IP block, e.g. if one SoC dedicates pins to that function but
> > > another doesn't. The driver won't know this, and will always
> > > attempt to set up the pinmux. The mapping table defines whether any
> > > HW programming is actually needed.
> > >
> > > Signed-off-by: Stephen Warren <[email protected]>
> >
> > This is equivalent to providing dummy pincontrollers as was on my
> > TODO for a while admittedly.
> >
> > For consistency with regulators it would maybe be better to have
> > optional dummy pin controllers but after thinking a bit about it
> > I think this is more helpful, so I applied it anyway.
> >
> > However I would invite more opinions...
>
> I'm afraid this is a little error-prone, that means even we specifed
> the wrong map name or state name, the pinctrl_get still does not get
> failed and it is a little different as what we want in this patch.
Yes, this does open up a small opportunity for an undetected error at
this stage in the patch series.
However, this is closed later by the final patch that enhances the mapping
table to represent pin config data, and "dummy" states.
I wrote/posted this patch to highlight that this code should be checking
for non-existent states, rather than states which match no mapping table
entries. Admittedly, there's no way to represent the difference at this
point in the patch series. Once the final patch is applied, there's an
explicit way to represent a state that exists, but has no mapping table
entries, so the opportunity for error then no longer exists.
--
nvpublic
On Mon, Feb 20, 2012 at 7:45 AM, Stephen Warren <[email protected]> wrote:
> struct pinctrl_dev's pin_desc_tree_lock and pinctrl_hogs_lock aren't
> useful; the data they protect is read-only except when registering or
> unregistering a pinctrl_dev, and at those times, it doesn't make sense to
> protect one part of the structure independently from the rest.
OK makes sense, please split this into a separate patch.
> struct pinctrl_dev's gpio_ranges_lock isn't effective;
> pinctrl_match_gpio_range() only holds this lock while searching for a gpio
> range, but the found range is return and manipulated after releading the
> lock. This could allow pinctrl_remove_gpio_range() for that range while it
> is in use, and the caller may very well delete the range after removing it,
> causing pinctrl code to touch the now-free range object.
>
> Solving this requires the introduction of a higher-level lock, at least
> a lock per pin controller, which both gpio range registration and
> pinctrl_get()/put() will acquire.
I don't really like this "big pinctrl lock" approach, atleast for the
gpio ranges the proper approach would rather be to use RCU,
would it not? The above looks like a textbook example of where
RCU should be used.
> There is missing locking on HW programming; pin controllers may pack the
> configuration for different pins/groups/config options/... into one
> register, and hence have to read-modify-write the register. This needs to
> be protected, but currently isn't.
Isn't that the responsibility of the driver? The subsystem
should not make assumptions of what locking the driver
may need of some drivers don't need it.
> Related, a future change will add a
> "complete" op to the pin controller drivers, the idea being that each
> state's programming will be programmed into the pinctrl driver followed
> by the "complete" call, which may e.g. flush a register cache to HW. For
> this to work, it must not be possible to interleave the pinctrl driver
> calls for different devices.
>
> As above, solving this requires the introduction of a higher-level lock,
> at least a lock per pin controller, which will be held for the duration
> of any pinctrl_enable()/disable() call.
I buy this reasoning though, we sure need something there, but
then it can be introduced with the complete() call, and be a
separate lock across the affected call.
> However, each pinctrl mapping table entry may affect a different pin
> controller if necessary. Hence, with a per-pin-controller lock, almost
> any pinctrl API may need to acquire multiple locks, one per controller.
> To avoid deadlock, these would need to be acquired in the same order in
> all cases. This is extremely difficult to implement in the case of
> pinctrl_get(), which doesn't know which pin controllers to lock until it
> has parsed the entire mapping table, since it contains somewhat arbitrary
> data.
>
> The simplest solution here is to introduce a single lock that covers all
> pin controllers at once. This will be acquired by all pinctrl APIs.
>
> This then makes struct pinctrl's mutex irrelevant, since that single lock
> will always be held whenever this mutex is currently held.
Introducing a big pincontroller lock :-(
As with the big kernel lock was the simplest approach to CPU
locking.
I really would like to hold back on this, is it really that hard to have
a more fine-granular locking here? Maybe this is a sign that we need
to have the list of states sorted in pincontroller order simply?
In that case we only need a lock per pincontroller I think.
Yours,
Linus Walleij
On Mon, Feb 20, 2012 at 7:45 AM, Stephen Warren <[email protected]> wrote:
> pinconf_groups_show() wrote all debug information on one line. Fix it to
> match pinconf_pins_show() and be legible.
>
> Signed-off-by: Stephen Warren <[email protected]>
Thanks, applied.
Linus Walleij
Dong Aisheng wrote at Tuesday, February 21, 2012 11:35 PM:
> On Tue, Feb 21, 2012 at 09:46:01AM -0800, Stephen Warren wrote:
> ....
> > > we might just
> > >
> > > #define PIN_MAP_NAME_DEFAULT "default"
> > > In <linux/pinctrl/consumer.h> and <linux/pinctrl/machine.h> alike,
> > > maybe in some <linux/pinctrl/mapnames.h> that both of these
> > > include?
> > >
> > > the have the driver ask for:
> > >
> > > sirfport->p = pinctrl_get(&pdev->dev, PIN_MAP_NAME_DEFAULT);
> > >
> > > (Similar changes can be done for U300, naming all its map
> > > "default".)
> >
> > I guess we could just modify pinmux_get() such that if NULL is passed as
> > the state name, it uses "default" instead internally. The disadvantage I
> > see here is that someone reading the client driver and writing the mapping
> > table then has to know that pinmux_get() does that internally, rather than
> > it being obvious right in the client driver code.
>
> It looks like a way out.
> The left problem seems to be that we may force the mapping table writer to
> specify "default" name for map at least.
> Is there any way to avoid it?
That specific restriction has been present since the very first patch
that created the pinctrl subsystem.
> I just think it may be better if we do not have such restriction.
Given that all map entries have a name, I'd really prefer that all drivers
had to request a specific matching name, rather than saying "just give me
whatever is in the mapping table".
I don't see this as a restriction, but more of a correctness issue;
every mapping table entry has a name and drivers (or device tree bindings)
define what that name must be, so why shouldn't drivers be required to
request that specific name, and experience an error if the mapping table
author didn't create that name?
regulator_get(dev, id) requires id != NULL.
clk_get(dev, con_id) requires con_id != NULL in order to match a clock
that has a non-NULL con_id defined (although clocks with a NULL con_id
are also legal, in which case, the con_id parameter to clk_get is
ignored)
So pinctrl_get(dev, state) requiring state != NULL seems consistent
with existing practice.
--
nvpublic
Linus Walleij wrote at Wednesday, February 22, 2012 10:39 AM:
> On Mon, Feb 20, 2012 at 7:45 AM, Stephen Warren <[email protected]> wrote:
>
> > struct pinctrl_dev's pin_desc_tree_lock and pinctrl_hogs_lock aren't
> > useful; the data they protect is read-only except when registering or
> > unregistering a pinctrl_dev, and at those times, it doesn't make sense to
> > protect one part of the structure independently from the rest.
>
> OK makes sense, please split this into a separate patch.
>
> > struct pinctrl_dev's gpio_ranges_lock isn't effective;
> > pinctrl_match_gpio_range() only holds this lock while searching for a gpio
> > range, but the found range is return and manipulated after releading the
> > lock. This could allow pinctrl_remove_gpio_range() for that range while it
> > is in use, and the caller may very well delete the range after removing it,
> > causing pinctrl code to touch the now-free range object.
> >
> > Solving this requires the introduction of a higher-level lock, at least
> > a lock per pin controller, which both gpio range registration and
> > pinctrl_get()/put() will acquire.
>
> I don't really like this "big pinctrl lock" approach, atleast for the
> gpio ranges the proper approach would rather be to use RCU,
> would it not? The above looks like a textbook example of where
> RCU should be used.
I'm not familiar with RCU specifically. If it's a single-writer-or-
multiple-reader lock, that might well solve this issue.
> > There is missing locking on HW programming; pin controllers may pack the
> > configuration for different pins/groups/config options/... into one
> > register, and hence have to read-modify-write the register. This needs to
> > be protected, but currently isn't.
>
> Isn't that the responsibility of the driver? The subsystem
> should not make assumptions of what locking the driver
> may need of some drivers don't need it.
Deferring this to drivers might make sense. However, drivers don't have
any way to do this right now, since they don't know when the start of
a programming operation is. I suppose when adding complete() we could
add a start() operation too, so the lock could be acquired there.
> > Related, a future change will add a
> > "complete" op to the pin controller drivers, the idea being that each
> > state's programming will be programmed into the pinctrl driver followed
> > by the "complete" call, which may e.g. flush a register cache to HW. For
> > this to work, it must not be possible to interleave the pinctrl driver
> > calls for different devices.
> >
> > As above, solving this requires the introduction of a higher-level lock,
> > at least a lock per pin controller, which will be held for the duration
> > of any pinctrl_enable()/disable() call.
>
> I buy this reasoning though, we sure need something there, but
> then it can be introduced with the complete() call, and be a
> separate lock across the affected call.
>
> > However, each pinctrl mapping table entry may affect a different pin
> > controller if necessary. Hence, with a per-pin-controller lock, almost
> > any pinctrl API may need to acquire multiple locks, one per controller.
> > To avoid deadlock, these would need to be acquired in the same order in
> > all cases. This is extremely difficult to implement in the case of
> > pinctrl_get(), which doesn't know which pin controllers to lock until it
> > has parsed the entire mapping table, since it contains somewhat arbitrary
> > data.
> >
> > The simplest solution here is to introduce a single lock that covers all
> > pin controllers at once. This will be acquired by all pinctrl APIs.
> >
> > This then makes struct pinctrl's mutex irrelevant, since that single lock
> > will always be held whenever this mutex is currently held.
>
> Introducing a big pincontroller lock :-(
>
> As with the big kernel lock was the simplest approach to CPU
> locking.
>
> I really would like to hold back on this, is it really that hard to have
> a more fine-granular locking here? Maybe this is a sign that we need
> to have the list of states sorted in pincontroller order simply?
> In that case we only need a lock per pincontroller I think.
I'd rather not alter the order that the mapping table entries get applied
in; I think that'd be confusing. I can certainly envisage use-cases where
the order is important (e.g. must disable pin config feature X before
enabling pin config feature Y when switching states, to avoid HW damage)
and sorting the mapping table would violating such requirements much more
likely.
Perhaps pinctrl_get() should keep a separate list of all pin controllers
involved anywhere in all the struct pinctrl_settings it contains, and
keep that list sorted, so that lock()/unlock() could be applied to that
list up-front, rather than locking pin controllers lazily as the settings
are applied in order. That'd be a bit more work but would probably allow
us to avoid any global locks.
Then, I think we could get away with:
A global lock for (un)registering controllers, (un)registering mapping
table entries, (un)registering GPIO ranges, parsing the mapping tables,
but which would not be taken when simply programming HW.
I'm not sure whether breaking this up into multiple locks actually makes
any sense; all of the above are relatively rare slow-paths anyway. The
important thing would be to not take that lock when /just/ programming
HW for state changes.
A lock per pin controller, implemented internally to the pin controller
driver if required in begin()/end() ops.
Does that seem reasonable?
Related to that, I guess we're currently missing refcounts on pin
controllers and GPIO ranges, so they can't be unregistered if
pinctrl_get() returned an object that references them, or gpio_request()
was called on a GPIO.
--
nvpublic
Stephen Warren wrote at Wednesday, February 22, 2012 11:27 AM:
> Linus Walleij wrote at Wednesday, February 22, 2012 10:39 AM:
> > On Mon, Feb 20, 2012 at 7:45 AM, Stephen Warren <[email protected]> wrote:
> >
> > > struct pinctrl_dev's pin_desc_tree_lock and pinctrl_hogs_lock aren't
> > > useful; the data they protect is read-only except when registering or
> > > unregistering a pinctrl_dev, and at those times, it doesn't make sense to
> > > protect one part of the structure independently from the rest.
> >
> > OK makes sense, please split this into a separate patch.
> >
> > > struct pinctrl_dev's gpio_ranges_lock isn't effective;
> > > pinctrl_match_gpio_range() only holds this lock while searching for a gpio
> > > range, but the found range is return and manipulated after releading the
> > > lock. This could allow pinctrl_remove_gpio_range() for that range while it
> > > is in use, and the caller may very well delete the range after removing it,
> > > causing pinctrl code to touch the now-free range object.
> > >
> > > Solving this requires the introduction of a higher-level lock, at least
> > > a lock per pin controller, which both gpio range registration and
> > > pinctrl_get()/put() will acquire.
> >
> > I don't really like this "big pinctrl lock" approach, atleast for the
> > gpio ranges the proper approach would rather be to use RCU,
> > would it not? The above looks like a textbook example of where
> > RCU should be used.
>
> I'm not familiar with RCU specifically. If it's a single-writer-or-
> multiple-reader lock, that might well solve this issue.
I don't think RCU is the answer here:
* RCU is great where the read path needs to be really fast at the (slight?)
cost of write path speed. In pinctrl, I don't see that the paths that
touch the GPIO ranges are especially time-critical since they're mostly
probe/remove-time actions.
* RCU is easy to use for simple cases, but more tricky where you want to
e.g. modify list elements in-place. While we don't right now, I'd like
to add a "usecount" to the gpio_range, so we can guarantee one can't be
unregistered while there's an active gpio_request() against it.
Otherwise, it'd be impossible to gpio_free() later.
* RCU knows when you're done with something due to pre-emption. However,
the internals of a pinctrl driver's gpio_request_enable might sleep e.g.
if it needed to touch registers on an I2C bus. While there is a sleepable
RCU, I don't think there's an sleepable equivalent of rculist.h.
...
> > Introducing a big pincontroller lock :-(
> >
> > As with the big kernel lock was the simplest approach to CPU
> > locking.
> >
> > I really would like to hold back on this, is it really that hard to have
> > a more fine-granular locking here? Maybe this is a sign that we need
> > to have the list of states sorted in pincontroller order simply?
> > In that case we only need a lock per pincontroller I think.
>
> I'd rather not alter the order that the mapping table entries get applied
> in; I think that'd be confusing. I can certainly envisage use-cases where
> the order is important (e.g. must disable pin config feature X before
> enabling pin config feature Y when switching states, to avoid HW damage)
> and sorting the mapping table would violating such requirements much more
> likely.
>
> Perhaps pinctrl_get() should keep a separate list of all pin controllers
> involved anywhere in all the struct pinctrl_settings it contains, and
> keep that list sorted, so that lock()/unlock() could be applied to that
> list up-front, rather than locking pin controllers lazily as the settings
> are applied in order. That'd be a bit more work but would probably allow
> us to avoid any global locks.
>
> Then, I think we could get away with:
>
> A global lock for (un)registering controllers, (un)registering mapping
> table entries, (un)registering GPIO ranges, parsing the mapping tables,
> but which would not be taken when simply programming HW.
>
> I'm not sure whether breaking this up into multiple locks actually makes
> any sense; all of the above are relatively rare slow-paths anyway. The
> important thing would be to not take that lock when /just/ programming
> HW for state changes.
>
> A lock per pin controller, implemented internally to the pin controller
> driver if required in begin()/end() ops.
>
> Does that seem reasonable?
>
> Related to that, I guess we're currently missing refcounts on pin
> controllers and GPIO ranges, so they can't be unregistered if
> pinctrl_get() returned an object that references them, or gpio_request()
> was called on a GPIO.
I did start looking into having separate locks, and I don't think it's
really feasible; I'd still like to go with the above; one lock for any
slow-path data-manipulation and one per "struct pinctrl *p" to allow
parallelism in the fast path. Some examples of issues with lots of locks:
It'd be nice to have a lock per struct pinctrl_dev.
I'd like to add a usecount to struct pinctrl_dev. Any struct pinctrl that
uses a struct pinctrl_dev, or any gpio_request will increase the usecount,
so that the struct pinctrl_dev can't be unregistered while a struct pinctrl
or GPIO could use it. That'd require something like the following at the
end of pinctrl_register():
mutex_lock(&pinctrldev_list_mutex);
/*
* Must do this first, because pinctrl_get needs to find this
* device in the list in order to convert mapping table entries
*/
list_add_tail(&pctldev->node, &pinctrldev_list);
/*
* This must be held so that when pinctrldev_list_mutex is dropped,
* other threads still can't touch pctldev and mess with it usecount
* until we're through here. This could be done before the first
* mutex_lock above too.
*/
mutex_lock(&pctldev->mutex);
/* Done with list manipulations now */
mutex_unlock(&pinctrldev_list_mutex);
pctldev->p = pinctrl_get(pctldev->dev, "default");
if (!IS_ERR(pctldev->p))
pinctrl_enable(pctldev->p);
pctldev->usecount_post_hog = pctldev->usecount;
But, the internals of pinctrl_get() will need to increment the usecount
of every pctldev it finds referenced from the mapping table. To do this,
the pctldev must be locked since data inside it is being manipulated.
However, that'd end up attempting to recursively lock this pctldev's
lock, and Linux locks don't allow recursive locking.
Perhaps this could be solved by passing a bunch of parameters into
pinctrl_get (or rather, an internal function called both from the public
pinctrl_get and here) indicating what was already locked. However, that
seems pretty nasty, and certainly not very simple.
Or perhaps, we should write some internal pinctrl_get that knows not to
touch the pctldev's own usecount, so that we don't need the separate
usecount_post_hog field, since that pinctrl_get wouldn't increment the
regular usecount. However, that'd be a nasty special case to maintain.
So then I figured, let's just remove pctldev->mutex and use
pinctrldev_list_mutex to cover both the list, and any/all struct
pinctrl_dev manipulations. This has the nice advantage that pinctrl_get()
no longer needs to lock/unlock a mutex for every mapping table entry, so
speeds things up.
At this point, we could still have separate mutexes for:
pinctrldev_list_mutex: Any operation on a device.
pinctrl_list_mutex: Any operation on the list of struct pinctrl.
pinctrl_maps: Any operation on the mapping table list.
But then let's take a look at the public pinctrl_get: It needs to lock
pinctrldev_list_mutex and pinctrl_maps for most of its operation, and
pinctrl_list_mutex for a little.
Equally, pinctrl_put needs to lock pinctrldev_list_mutex for most of
its operation since it'd be decreasing many struct pinctrl_dev.usecount
in general, or at least doing it many times on a single pctldev. It'd
need to lock pinctrl_list_mutex for at least a little.
All the GPIO functions also manipulate pctldev usecounts, so would need
to hold pinctrldev_list_mutex for the data-manipulation portions of their
run-time.
So, pinctrldev_list_mutex is almost a single global mutex anyway, except
there are a bunch of other mutexes hanging around making life complex.
It turns out that the only real parallelism is:
pinctrl_register_mappings: Only needs pinctrl_maps, but this is probably
the rarest operation and hardly needs to run parallel.
Every other list-manipulation operation needs to lock pinctrldev_list_mutex
for either the majority of the time, or over-and-over so may as well just
do it once.
pinctrl_enable/disable: The fast path. I think we can usefully have a
separate mutex per each of these as I mentioned in the email I'm quoting.
So it seems again that we really need a single slow-path mutex, and a
per-struct-pinctrl fast-path mutex.
--
nvpublic
On Wed, Feb 22, 2012 at 10:05:20AM -0800, Stephen Warren wrote:
> Dong Aisheng wrote at Tuesday, February 21, 2012 11:35 PM:
> > On Tue, Feb 21, 2012 at 09:46:01AM -0800, Stephen Warren wrote:
> > ....
> > > > we might just
> > > >
> > > > #define PIN_MAP_NAME_DEFAULT "default"
> > > > In <linux/pinctrl/consumer.h> and <linux/pinctrl/machine.h> alike,
> > > > maybe in some <linux/pinctrl/mapnames.h> that both of these
> > > > include?
> > > >
> > > > the have the driver ask for:
> > > >
> > > > sirfport->p = pinctrl_get(&pdev->dev, PIN_MAP_NAME_DEFAULT);
> > > >
> > > > (Similar changes can be done for U300, naming all its map
> > > > "default".)
> > >
> > > I guess we could just modify pinmux_get() such that if NULL is passed as
> > > the state name, it uses "default" instead internally. The disadvantage I
> > > see here is that someone reading the client driver and writing the mapping
> > > table then has to know that pinmux_get() does that internally, rather than
> > > it being obvious right in the client driver code.
> >
> > It looks like a way out.
>
> > The left problem seems to be that we may force the mapping table writer to
> > specify "default" name for map at least.
> > Is there any way to avoid it?
>
> That specific restriction has been present since the very first patch
> that created the pinctrl subsystem.
>
Since i saw some code in pinctrl subsystem formerly like:
/*
* If we're looking for a specific named map, this must match,
* else we loop and look for the next.
*/
if (name != NULL) {
if (map->name == NULL)
continue;
if (strcmp(map->name, name))
continue;
}
So i guessed the map->name could be NULL in the original design.
Of course, if we used the convenience macro to define map, there's no
chance to make map name NULL.
We did not force users to must convenience macros, right?
> > I just think it may be better if we do not have such restriction.
>
> Given that all map entries have a name, I'd really prefer that all drivers
> had to request a specific matching name, rather than saying "just give me
> whatever is in the mapping table".
>
> I don't see this as a restriction, but more of a correctness issue;
> every mapping table entry has a name and drivers (or device tree bindings)
> define what that name must be, so why shouldn't drivers be required to
> request that specific name, and experience an error if the mapping table
> author didn't create that name?
>
Yes, i agree.
Based on this point, i feel maybe internally convert NULL to a "default" name for
pinctrl_get does not make too much sense.
> regulator_get(dev, id) requires id != NULL.
>
> clk_get(dev, con_id) requires con_id != NULL in order to match a clock
> that has a non-NULL con_id defined (although clocks with a NULL con_id
> are also legal, in which case, the con_id parameter to clk_get is
> ignored)
>
> So pinctrl_get(dev, state) requiring state != NULL seems consistent
> with existing practice.
>
Yes, it's true if given all map entries have a name.
Now i'm intend to the way you mentioned at:
https://lkml.org/lkml/2012/2/21/213
And i agree with the way you said:
If we continue to allow NULL names, I think we should change that to:
if name:
match = map->name && !strcmp(name, map->name)
else:
match = !map->name
And i think allowing map name to be NULL will make life easy for those
devices who do not support multi states.
Originally i'm wondering how about more than one entries with a NULL name.
But now i think it's actually not an issue since we indeed support multi
entries with the same map name.
Regards
Dong Aisheng
Dong Aisheng wrote at Wednesday, February 22, 2012 8:35 PM:
> On Wed, Feb 22, 2012 at 10:05:20AM -0800, Stephen Warren wrote:
> > Dong Aisheng wrote at Tuesday, February 21, 2012 11:35 PM:
> > > On Tue, Feb 21, 2012 at 09:46:01AM -0800, Stephen Warren wrote:
> > > ....
> > > > > we might just
> > > > >
> > > > > #define PIN_MAP_NAME_DEFAULT "default"
> > > > > In <linux/pinctrl/consumer.h> and <linux/pinctrl/machine.h> alike,
> > > > > maybe in some <linux/pinctrl/mapnames.h> that both of these
> > > > > include?
> > > > >
> > > > > the have the driver ask for:
> > > > >
> > > > > sirfport->p = pinctrl_get(&pdev->dev, PIN_MAP_NAME_DEFAULT);
> > > > >
> > > > > (Similar changes can be done for U300, naming all its map
> > > > > "default".)
> > > >
> > > > I guess we could just modify pinmux_get() such that if NULL is passed as
> > > > the state name, it uses "default" instead internally. The disadvantage I
> > > > see here is that someone reading the client driver and writing the mapping
> > > > table then has to know that pinmux_get() does that internally, rather than
> > > > it being obvious right in the client driver code.
> > >
> > > It looks like a way out.
> >
> > > The left problem seems to be that we may force the mapping table writer to
> > > specify "default" name for map at least.
> > > Is there any way to avoid it?
> >
> > That specific restriction has been present since the very first patch
> > that created the pinctrl subsystem.
>
> Since i saw some code in pinctrl subsystem formerly like:
> /*
> * If we're looking for a specific named map, this must match,
> * else we loop and look for the next.
> */
> if (name != NULL) {
> if (map->name == NULL)
> continue;
> if (strcmp(map->name, name))
> continue;
> }
> So i guessed the map->name could be NULL in the original design.
> Of course, if we used the convenience macro to define map, there's no
> chance to make map name NULL.
Admittedly, the code is a little inconsistent. I was thinking of:
+int __init pinmux_register_mappings(struct pinmux_map const *maps,
...
+ for (i = 0; i < num_maps; i++) {
+ /* Sanity check the mapping */
+ if (!maps[i].name) {
+ pr_err("failed to register map %d: "
+ "no map name given\n", i);
+ return -EINVAL;
+ }
> We did not force users to must convenience macros, right?
No. In fact, my patches for Tegra's board file didn't always use them.
> > > I just think it may be better if we do not have such restriction.
> >
> > Given that all map entries have a name, I'd really prefer that all drivers
> > had to request a specific matching name, rather than saying "just give me
> > whatever is in the mapping table".
> >
> > I don't see this as a restriction, but more of a correctness issue;
> > every mapping table entry has a name and drivers (or device tree bindings)
> > define what that name must be, so why shouldn't drivers be required to
> > request that specific name, and experience an error if the mapping table
> > author didn't create that name?
>
> Yes, i agree.
> Based on this point, i feel maybe internally convert NULL to a "default" name for
> pinctrl_get does not make too much sense.
>
> > regulator_get(dev, id) requires id != NULL.
> >
> > clk_get(dev, con_id) requires con_id != NULL in order to match a clock
> > that has a non-NULL con_id defined (although clocks with a NULL con_id
> > are also legal, in which case, the con_id parameter to clk_get is
> > ignored)
> >
> > So pinctrl_get(dev, state) requiring state != NULL seems consistent
> > with existing practice.
>
> Yes, it's true if given all map entries have a name.
>
> Now i'm intend to the way you mentioned at:
> https://lkml.org/lkml/2012/2/21/213
>
> And i agree with the way you said:
> If we continue to allow NULL names, I think we should change that to:
> if name:
> match = map->name && !strcmp(name, map->name)
> else:
> match = !map->name
>
> And i think allowing map name to be NULL will make life easy for those
> devices who do not support multi states.
It does make it a little convenient for board files, but isn't really
practical to implement for device-tree unless we modify the binding to
have something that means "no name". I'd rather not allow more options
in the binding though.
What's wrong with writing e.g. PINCTRL_DEFAULT instead of NULL when calling
pinctrl_get() or pinctrl_lookup_state() though? Given pinctrl.h having:
#define PINCTRL_DEFAULT "default"
> Originally I'm wondering how about more than one entries with a NULL name.
> But now i think it's actually not an issue since we indeed support multi
> entries with the same map name.
Yes.
If the mapping table contains a number of entries with the same string name,
they're all part of the same single state with that name.
If entries with a name field set to NULL are allowed and exist, I'd similarly
consider them all part of the same state, which just doesn't have a name.
--
nvpublic
On Wed, Feb 22, 2012 at 09:21:25AM -0800, Stephen Warren wrote:
...
> > I'm afraid this is a little error-prone, that means even we specifed
> > the wrong map name or state name, the pinctrl_get still does not get
> > failed and it is a little different as what we want in this patch.
>
> Yes, this does open up a small opportunity for an undetected error at
> this stage in the patch series.
>
> However, this is closed later by the final patch that enhances the mapping
> table to represent pin config data, and "dummy" states.
>
> I wrote/posted this patch to highlight that this code should be checking
> for non-existent states, rather than states which match no mapping table
> entries. Admittedly, there's no way to represent the difference at this
> point in the patch series. Once the final patch is applied, there's an
> explicit way to represent a state that exists, but has no mapping table
> entries, so the opportunity for error then no longer exists.
>
Ok, it's good.
Will see your final patch for this issue.
Regards
Dong Aisheng
On Wed, Feb 22, 2012 at 07:39:42PM -0800, Stephen Warren wrote:
> Dong Aisheng wrote at Wednesday, February 22, 2012 8:35 PM:
> > On Wed, Feb 22, 2012 at 10:05:20AM -0800, Stephen Warren wrote:
> > > Dong Aisheng wrote at Tuesday, February 21, 2012 11:35 PM:
> > > > On Tue, Feb 21, 2012 at 09:46:01AM -0800, Stephen Warren wrote:
> > > > ....
> > > > > > we might just
> > > > > >
> > > > > > #define PIN_MAP_NAME_DEFAULT "default"
> > > > > > In <linux/pinctrl/consumer.h> and <linux/pinctrl/machine.h> alike,
> > > > > > maybe in some <linux/pinctrl/mapnames.h> that both of these
> > > > > > include?
> > > > > >
> > > > > > the have the driver ask for:
> > > > > >
> > > > > > sirfport->p = pinctrl_get(&pdev->dev, PIN_MAP_NAME_DEFAULT);
> > > > > >
> > > > > > (Similar changes can be done for U300, naming all its map
> > > > > > "default".)
> > > > >
> > > > > I guess we could just modify pinmux_get() such that if NULL is passed as
> > > > > the state name, it uses "default" instead internally. The disadvantage I
> > > > > see here is that someone reading the client driver and writing the mapping
> > > > > table then has to know that pinmux_get() does that internally, rather than
> > > > > it being obvious right in the client driver code.
> > > >
> > > > It looks like a way out.
> > >
> > > > The left problem seems to be that we may force the mapping table writer to
> > > > specify "default" name for map at least.
> > > > Is there any way to avoid it?
> > >
> > > That specific restriction has been present since the very first patch
> > > that created the pinctrl subsystem.
> >
> > Since i saw some code in pinctrl subsystem formerly like:
> > /*
> > * If we're looking for a specific named map, this must match,
> > * else we loop and look for the next.
> > */
> > if (name != NULL) {
> > if (map->name == NULL)
> > continue;
> > if (strcmp(map->name, name))
> > continue;
> > }
> > So i guessed the map->name could be NULL in the original design.
> > Of course, if we used the convenience macro to define map, there's no
> > chance to make map name NULL.
>
> Admittedly, the code is a little inconsistent. I was thinking of:
>
> +int __init pinmux_register_mappings(struct pinmux_map const *maps,
> ...
> + for (i = 0; i < num_maps; i++) {
> + /* Sanity check the mapping */
> + if (!maps[i].name) {
> + pr_err("failed to register map %d: "
> + "no map name given\n", i);
> + return -EINVAL;
> + }
>
> > We did not force users to must convenience macros, right?
>
> No. In fact, my patches for Tegra's board file didn't always use them.
>
> > > > I just think it may be better if we do not have such restriction.
> > >
> > > Given that all map entries have a name, I'd really prefer that all drivers
> > > had to request a specific matching name, rather than saying "just give me
> > > whatever is in the mapping table".
> > >
> > > I don't see this as a restriction, but more of a correctness issue;
> > > every mapping table entry has a name and drivers (or device tree bindings)
> > > define what that name must be, so why shouldn't drivers be required to
> > > request that specific name, and experience an error if the mapping table
> > > author didn't create that name?
> >
> > Yes, i agree.
> > Based on this point, i feel maybe internally convert NULL to a "default" name for
> > pinctrl_get does not make too much sense.
> >
> > > regulator_get(dev, id) requires id != NULL.
> > >
> > > clk_get(dev, con_id) requires con_id != NULL in order to match a clock
> > > that has a non-NULL con_id defined (although clocks with a NULL con_id
> > > are also legal, in which case, the con_id parameter to clk_get is
> > > ignored)
> > >
> > > So pinctrl_get(dev, state) requiring state != NULL seems consistent
> > > with existing practice.
> >
> > Yes, it's true if given all map entries have a name.
> >
> > Now i'm intend to the way you mentioned at:
> > https://lkml.org/lkml/2012/2/21/213
> >
> > And i agree with the way you said:
> > If we continue to allow NULL names, I think we should change that to:
> > if name:
> > match = map->name && !strcmp(name, map->name)
> > else:
> > match = !map->name
> >
> > And i think allowing map name to be NULL will make life easy for those
> > devices who do not support multi states.
>
> It does make it a little convenient for board files, but isn't really
> practical to implement for device-tree unless we modify the binding to
> have something that means "no name". I'd rather not allow more options
> in the binding though.
>
> What's wrong with writing e.g. PINCTRL_DEFAULT instead of NULL when calling
> pinctrl_get() or pinctrl_lookup_state() though? Given pinctrl.h having:
>
> #define PINCTRL_DEFAULT "default"
>
First, map writer needs know this logic.
Second, all as you said:
> > > every mapping table entry has a name and drivers (or device tree bindings)
> > > define what that name must be, so why shouldn't drivers be required to
> > > request that specific name, and experience an error if the mapping table
> > > author didn't create that name?
if want to keep align with regulator and clock,
i just feel a little that it does not make too much sense to
internally convert NULL to "default", right?
Regards
Dong Aisheng
Dong Aisheng wrote at Wednesday, February 22, 2012 8:57 PM:
> On Wed, Feb 22, 2012 at 07:39:42PM -0800, Stephen Warren wrote:
> > Dong Aisheng wrote at Wednesday, February 22, 2012 8:35 PM:
> > > On Wed, Feb 22, 2012 at 10:05:20AM -0800, Stephen Warren wrote:
...
> > > > regulator_get(dev, id) requires id != NULL.
> > > >
> > > > clk_get(dev, con_id) requires con_id != NULL in order to match a clock
> > > > that has a non-NULL con_id defined (although clocks with a NULL con_id
> > > > are also legal, in which case, the con_id parameter to clk_get is
> > > > ignored)
> > > >
> > > > So pinctrl_get(dev, state) requiring state != NULL seems consistent
> > > > with existing practice.
> > >
> > > Yes, it's true if given all map entries have a name.
> > >
> > > Now i'm intend to the way you mentioned at:
> > > https://lkml.org/lkml/2012/2/21/213
> > >
> > > And i agree with the way you said:
> > > If we continue to allow NULL names, I think we should change that to:
> > > if name:
> > > match = map->name && !strcmp(name, map->name)
> > > else:
> > > match = !map->name
> > >
> > > And i think allowing map name to be NULL will make life easy for those
> > > devices who do not support multi states.
> >
> > It does make it a little convenient for board files, but isn't really
> > practical to implement for device-tree unless we modify the binding to
> > have something that means "no name". I'd rather not allow more options
> > in the binding though.
> >
> > What's wrong with writing e.g. PINCTRL_DEFAULT instead of NULL when calling
> > pinctrl_get() or pinctrl_lookup_state() though? Given pinctrl.h having:
> >
> > #define PINCTRL_DEFAULT "default"
>
> First, map writer needs know this logic.
Sure, but that's always true; you need to know the state name in all cases.
And this requirement seems extremely trivial for a map writer to implement.
> Second, all as you said:
>
> > > > every mapping table entry has a name and drivers (or device tree bindings)
> > > > define what that name must be, so why shouldn't drivers be required to
> > > > request that specific name, and experience an error if the mapping table
> > > > author didn't create that name?
>
> if want to keep align with regulator and clock,
> i just feel a little that it does not make too much sense to
> internally convert NULL to "default", right?
I'm hoping that we don't do this internal conversion. The rules I'd like are:
* Every mapping table entry must include a non-NULL name field.
* Every call to pinctrl_get()/pinctrl_lookup_state() must pass a non-NULL name
----------==========----------==========----------==========----------==========--
nvpublic
On Wed, Feb 22, 2012 at 07:53:44PM -0800, Stephen Warren wrote:
> Dong Aisheng wrote at Wednesday, February 22, 2012 8:57 PM:
> > On Wed, Feb 22, 2012 at 07:39:42PM -0800, Stephen Warren wrote:
> > > Dong Aisheng wrote at Wednesday, February 22, 2012 8:35 PM:
> > > > On Wed, Feb 22, 2012 at 10:05:20AM -0800, Stephen Warren wrote:
> ...
> > > > > regulator_get(dev, id) requires id != NULL.
> > > > >
> > > > > clk_get(dev, con_id) requires con_id != NULL in order to match a clock
> > > > > that has a non-NULL con_id defined (although clocks with a NULL con_id
> > > > > are also legal, in which case, the con_id parameter to clk_get is
> > > > > ignored)
> > > > >
> > > > > So pinctrl_get(dev, state) requiring state != NULL seems consistent
> > > > > with existing practice.
> > > >
> > > > Yes, it's true if given all map entries have a name.
> > > >
> > > > Now i'm intend to the way you mentioned at:
> > > > https://lkml.org/lkml/2012/2/21/213
> > > >
> > > > And i agree with the way you said:
> > > > If we continue to allow NULL names, I think we should change that to:
> > > > if name:
> > > > match = map->name && !strcmp(name, map->name)
> > > > else:
> > > > match = !map->name
> > > >
> > > > And i think allowing map name to be NULL will make life easy for those
> > > > devices who do not support multi states.
> > >
> > > It does make it a little convenient for board files, but isn't really
> > > practical to implement for device-tree unless we modify the binding to
> > > have something that means "no name". I'd rather not allow more options
> > > in the binding though.
> > >
> > > What's wrong with writing e.g. PINCTRL_DEFAULT instead of NULL when calling
> > > pinctrl_get() or pinctrl_lookup_state() though? Given pinctrl.h having:
> > >
> > > #define PINCTRL_DEFAULT "default"
> >
> > First, map writer needs know this logic.
>
> Sure, but that's always true; you need to know the state name in all cases.
> And this requirement seems extremely trivial for a map writer to implement.
>
> > Second, all as you said:
> >
> > > > > every mapping table entry has a name and drivers (or device tree bindings)
> > > > > define what that name must be, so why shouldn't drivers be required to
> > > > > request that specific name, and experience an error if the mapping table
> > > > > author didn't create that name?
> >
> > if want to keep align with regulator and clock,
> > i just feel a little that it does not make too much sense to
> > internally convert NULL to "default", right?
>
> I'm hoping that we don't do this internal conversion. The rules I'd like are:
>
I'm also agree that we either allow map name to be NULL or not but not do internal
conversion.
> * Every mapping table entry must include a non-NULL name field.
>
> * Every call to pinctrl_get()/pinctrl_lookup_state() must pass a non-NULL name
This is a way.
Before using this, i'm still wondering what big problems do you think for us to support
a NULL map name?
Because the name for devices do not have different state really does not make too much
sense but extra overhead.
Regards
Dong Aisheng
On Mon, Feb 20, 2012 at 7:45 AM, Stephen Warren <[email protected]> wrote:
> The API model is changed from:
>
> p = pinctrl_get(dev, "state1");
> pinctrl_enable(p);
> ...
> pinctrl_disable(p);
> pinctrl_put(p);
> p = pinctrl_get(dev, "state2");
> pinctrl_enable(p);
> ...
> pinctrl_disable(p);
> pinctrl_put(p);
>
> to this:
>
> p = pinctrl_get(dev);
> s1 = pinctrl_lookup_state(p, "state1");
> s2 = pinctrl_lookup_state(p, "state2");
> pinctrl_select_state(p, s1);
> ...
> pinctrl_select_state(p, s2);
> ...
> pinctrl_put(p);
>
> This allows devices to directly transition between states without
> disabling the pin controller programming and put()/get()ing the
> configuration data each time. This model will also better suit pinconf
> programming, which doesn't have a concept of "disable".
>
> The special-case hogging feature of pin controllers is re-written to use
> the regular APIs instead of special-case code. Hence, the pinmux-hogs
> debugfs file is removed; see the top-level pinctrl-handles files for
> equivalent data.
>
> Signed-off-by: Stephen Warren <[email protected]>
Overall this is excellent and exactly what we have discussed and
just what we want, good job!
> ?static const struct pinctrl_map __initdata mapping[] = {
> ? ? ? ?{
> + ? ? ? ? ? ? ? .dev_name = "foo-spi.0",
> + ? ? ? ? ? ? ? .name = "default",
I think we should introduce a
#define PINCTRL_DEFAULT_STATE "default"
And use that #define in examples and code from day 1.
That will ease the transition to generalized states like
PINCTRL_IDLE_STATE etc further down the road.
> ?{
> + ? ? ? .dev_name = "foo-mmc.0",
> ? ? ? ?.name = "2bit"
> ? ? ? ?.ctrl_dev_name = "pinctrl-foo",
> ? ? ? ?.function = "mmc0",
> ? ? ? ?.group = "mmc0_1_grp",
> - ? ? ? .dev_name = "foo-mmc.0",
> ?},
> ?{
> + ? ? ? .dev_name = "foo-mmc.0",
> ? ? ? ?.name = "4bit"
> ? ? ? ?.ctrl_dev_name = "pinctrl-foo",
> ? ? ? ?.function = "mmc0",
> ? ? ? ?.group = "mmc0_1_grp",
> - ? ? ? .dev_name = "foo-mmc.0",
> ?},
> ?{
> + ? ? ? .dev_name = "foo-mmc.0",
> ? ? ? ?.name = "4bit"
> ? ? ? ?.ctrl_dev_name = "pinctrl-foo",
> ? ? ? ?.function = "mmc0",
> ? ? ? ?.group = "mmc0_2_grp",
> - ? ? ? .dev_name = "foo-mmc.0",
> ?},
> ?{
> + ? ? ? .dev_name = "foo-mmc.0",
> ? ? ? ?.name = "8bit"
> ? ? ? ?.ctrl_dev_name = "pinctrl-foo",
> + ? ? ? .function = "mmc0",
> ? ? ? ?.group = "mmc0_1_grp",
> - ? ? ? .dev_name = "foo-mmc.0",
> ?},
> ?{
> + ? ? ? .dev_name = "foo-mmc.0",
> ? ? ? ?.name = "8bit"
> ? ? ? ?.ctrl_dev_name = "pinctrl-foo",
> ? ? ? ?.function = "mmc0",
> ? ? ? ?.group = "mmc0_2_grp",
> - ? ? ? .dev_name = "foo-mmc.0",
> ?},
> ?{
> + ? ? ? .dev_name = "foo-mmc.0",
> ? ? ? ?.name = "8bit"
> ? ? ? ?.ctrl_dev_name = "pinctrl-foo",
> ? ? ? ?.function = "mmc0",
> ? ? ? ?.group = "mmc0_3_grp",
> - ? ? ? .dev_name = "foo-mmc.0",
> ?},
Seems like random reordering but no big deal, could go in separate
patch.
> ?The result of grabbing this mapping from the device with something like
> ?this (see next paragraph):
>
> - ? ? ? p = pinctrl_get(&device, "8bit");
> + ? ? ? p = pinctrl_get(dev);
> + ? ? ? s = pinctrl_lookup_state(p, "8bit");
> + ? ? ? ret = pinctrl_select_state(p, s);
> +
> +or more simply:
> +
> + ? ? ? p = pinctrl_get_select(dev, "8bit");
Ohhh sweet! I like pinctrl_get_select()!
> ?Pin control map entries can be hogged by the core when the pin controller
> -is registered. This means that the core will attempt to call pinctrl_get() and
> -pinctrl_enable() on it immediately after the pin control device has been
> -registered.
> +is registered. This means that the core will attempt to call pinctrl_get(),
> +lookup_state() and select_state() on it immediately after the pin control
> +device has been registered.
>
> -This is enabled by simply setting the .dev_name field in the map to the name
> -of the pin controller itself, like this:
> +This occurs for mapping table entries where the client device name is equal
> +to the pin controller device name, and the state name is "active".
>
> ?{
> - ? ? ? .name = "POWERMAP"
> + ? ? ? .dev_name = "pinctrl-foo",
> + ? ? ? .name = "active",
Again define a standard name, I think PINCTRL_STATE_DEFAULT
should be used for this too, since it means it defaults to active.
> -PIN_MAP_SYS_HOG("POWERMAP", "pinctrl-foo", "power_func")
> +PIN_MAP_SYS_HOG("active", "pinctrl-foo", "power_func")
Then use that PINCTRL_STATE_DEFAULT
> ?This snippet first muxes the function in the pins defined by group A, enables
> ?it, disables and releases it, and muxes it in on the pins defined by group B:
> @@ -1017,23 +1045,36 @@ it, disables and releases it, and muxes it in on the pins defined by group B:
> ?foo_switch()
> ?{
> ? ? ? ?struct pinctrl *p;
> + ? ? ? struct pinctrl_state *s1, *s2;
> +
> + ? ? ? /* Setup */
> + ? ? ? p = pinctrl_get(&device);
> + ? ? ? if (IS_ERR(p))
> + ? ? ? ? ? ? ? ...
> +
> + ? ? ? s1 = pinctrl_lookup_state(foo->p, "pos-A");
> + ? ? ? if (IS_ERR(s1))
> + ? ? ? ? ? ? ? ...
> +
> + ? ? ? s2 = pinctrl_lookup_state(foo->p, "pos-B");
> + ? ? ? if (IS_ERR(s2))
> + ? ? ? ? ? ? ? ...
>
> ? ? ? ?/* Enable on position A */
> - ? ? ? p = pinctrl_get(&device, "spi0-pos-A");
> - ? ? ? if IS_ERR(p)
> - ? ? ? ? ? ? ? return PTR_ERR(p);
> - ? ? ? pinctrl_enable(p);
> + ? ? ? ret = pinctrl_select_state(s);
> + ? ? ? if (ret < 0)
> + ? ? ? ? ? ...
>
> - ? ? ? /* This releases the pins again */
> - ? ? ? pinctrl_disable(p);
> - ? ? ? pinctrl_put(p);
> + ? ? ? ...
>
> ? ? ? ?/* Enable on position B */
> - ? ? ? p = pinctrl_get(&device, "spi0-pos-B");
> - ? ? ? if IS_ERR(p)
> - ? ? ? ? ? ? ? return PTR_ERR(p);
> - ? ? ? pinctrl_enable(p);
> + ? ? ? ret = pinctrl_select_state(s);
> + ? ? ? if (ret < 0)
> + ? ? ? ? ? ...
> +
> ? ? ? ?...
> +
> + ? ? ? pinctrl_put(p);
> ?}
This is looking real good. I think recent discussion with Russell
also ironed out the problems with potential gpio interaction.
> - ? ? ? PIN_MAP_SYS_HOG("POWER", "pinmux-u300", "power"),
> - ? ? ? PIN_MAP_SYS_HOG("EMIF0", "pinmux-u300", "emif0"),
> - ? ? ? PIN_MAP_SYS_HOG("EMIF1", "pinmux-u300", "emif1"),
> + ? ? ? PIN_MAP_SYS_HOG("default", "pinmux-u300", "power"),
> + ? ? ? PIN_MAP_SYS_HOG("default", "pinmux-u300", "emif0"),
> + ? ? ? PIN_MAP_SYS_HOG("default", "pinmux-u300", "emif1"),
> ? ? ? ?/* per-device maps for MMC/SD, SPI and UART */
> - ? ? ? PIN_MAP("MMCSD", "pinmux-u300", "mmc0", "mmci"),
> - ? ? ? PIN_MAP("SPI", "pinmux-u300", "spi0", "pl022"),
> - ? ? ? PIN_MAP("UART0", "pinmux-u300", "uart0", "uart0"),
> + ? ? ? PIN_MAP("default", "pinmux-u300", "mmc0", "mmci"),
> + ? ? ? PIN_MAP("default", "pinmux-u300", "spi0", "pl022"),
> + ? ? ? PIN_MAP("default", "pinmux-u300", "uart0", "uart0"),
> ?};
PINCTRL_STATE_DEFAULT
So far I really like this. I should look closer at the code but mainly
I just have to trust you on it and fix any bugs later, this change is
way more valuable as is.
Please move this patch as far to the head of the series as possible
so we can get it in, I guess you need the state lookup in struct pinctrl
to proceed but could we e.g. puy the locking changes after this?
Yours,
Linus Walleij
On Mon, Feb 20, 2012 at 7:46 AM, Stephen Warren <[email protected]> wrote:
> The pinctrl mapping table can now contain entries to:
> * Set the mux function of a pin group
> * Apply a set of pin config options to a pin or a group
>
> This allows pinctrl_select_state() to apply pin configs settings as well
> as mux settings.
>
> Signed-off-by: Stephen Warren <[email protected]>
Overall excellent, just smaller things below:
> @@ -817,7 +827,40 @@ it even more compact which assumes you want to use pinctrl-foo and position
> ?0 for mapping, for example:
>
> ?static struct pinctrl_map __initdata mapping[] = {
> - ? ? ? PIN_MAP("default", "pinctrl-foo", "i2c0", "foo-i2c.0"),
> + ? ? ? PIN_MAP_MUX_GROUP("foo-i2c.o", "default", "pinctrl-foo", NULL, "i2c0"),
> +};
OK looks good!
> +The mapping table may also contain pin configuration entries. It's common for
> +each pin/group to have a number of configuration entries that affect it, so
> +the table entries for configuration reference an array of config parameters
> +and values. An example using the convenience macros is shown below:
> +
> +static unsigned long i2c_grp_configs[] = {
> + ? ? ? FOO_PIN_DRIVEN,
> + ? ? ? FOO_PIN_PULLUP,
> +};
> +
> +static unsigned long i2c_pin_configs[] = {
> + ? ? ? FOO_OPEN_COLLECTOR,
> + ? ? ? FOO_SLEW_RATE_SLOW,
> +};
> +
> +static struct pinctrl_map __initdata mapping[] = {
> + ? ? ? PIN_MAP_MUX_GROUP("foo-i2c.0", "default", "pinctrl-foo", "i2c0", "i2c0"),
> + ? ? ? PIN_MAP_MUX_CONFIGS_GROUP("foo-i2c.0", "default", "pinctrl-foo", "i2c0", i2c_grp_configs),
> + ? ? ? PIN_MAP_MUX_CONFIGS_PIN("foo-i2c.0", "default", "pinctrl-foo", "i2c0scl", i2c_pin_configs),
> + ? ? ? PIN_MAP_MUX_CONFIGS_PIN("foo-i2c.0", "default", "pinctrl-foo", "i2c0sda", i2c_pin_configs),
> +};
I buy this too...
> +Finally, some devices expect the mapping table to contain certain specific
> +named states. When running on hardware that doesn't need any pin controller
> +configuration, the mapping table must still contain those named states, in
> +order to explicitly indicate that the states were provided and intended to
> +be empty. Table entry macro PIN_MAP_DUMMY_STATE serves the purpose of defining
> +a named state without causing any pin controller to be programmed:
> +
> +static struct pinctrl_map __initdata mapping[] = {
> + ? ? ? PIN_MAP_DUMMY_STATE("foo-i2c.0", "default"),
> ?};
Looks useful so why not.
> @@ -1022,7 +1074,7 @@ Since it may be common to request the core to hog a few always-applicable
> ?mux settings on the primary pin controller, there is a convenience macro for
> ?this:
>
> -PIN_MAP_SYS_HOG("active", "pinctrl-foo", "power_func")
> +PIN_MAP_MUX_GROUP("pinctrl-foo", "active", "pinctrl-foo", NULL, "power_func")
Please keep the explicit _HOG macros for readability. Relying on
the implicit relation between dev and pctldev being the same and to be
parsed by humans is vulnerable.
PIN_MAP_MUX_GROUP_HOG()
in this case, with the same arguments (though with PINCTRL_STATE_DEFAULT
in place for "active") is better IMO.
> ?/* Pinmux settings */
> ?static struct pinctrl_map __initdata u300_pinmux_map[] = {
> ? ? ? ?/* anonymous maps for chip power and EMIFs */
> - ? ? ? PIN_MAP_SYS_HOG("default", "pinmux-u300", "power"),
> - ? ? ? PIN_MAP_SYS_HOG("default", "pinmux-u300", "emif0"),
> - ? ? ? PIN_MAP_SYS_HOG("default", "pinmux-u300", "emif1"),
> + ? ? ? PIN_MAP_MUX_GROUP("pinmux-u300", "default", "pinmux-u300", NULL, "power"),
> + ? ? ? PIN_MAP_MUX_GROUP("pinmux-u300", "default", "pinmux-u300", NULL, "emif0"),
> + ? ? ? PIN_MAP_MUX_GROUP("pinmux-u300", "default", "pinmux-u300", NULL, "emif1"),
> ? ? ? ?/* per-device maps for MMC/SD, SPI and UART */
> - ? ? ? PIN_MAP("default", "pinmux-u300", "mmc0", "mmci"),
> - ? ? ? PIN_MAP("default", "pinmux-u300", "spi0", "pl022"),
> - ? ? ? PIN_MAP("default", "pinmux-u300", "uart0", "uart0"),
> + ? ? ? PIN_MAP_MUX_GROUP("mmci", ?"default", "pinmux-u300", NULL, "mmc0"),
> + ? ? ? PIN_MAP_MUX_GROUP("pl022", "default", "pinmux-u300", NULL, "spi0"),
> + ? ? ? PIN_MAP_MUX_GROUP("uart0", "default", "pinmux-u300", NULL, "uart0"),
> ?};
PIN_MAP_MUX_GROUP_HOG() please. PINCTRL_STATE_DEFAULT instead
of "default".
Or maybe we should imply that PIN_MAP_MUX_GROUP_HOG() hogs the
default state, or have PIN_MAP_MUX_GROUP_HOG_DEFAULT() even?
> --- a/drivers/pinctrl/core.c
> +++ b/drivers/pinctrl/core.c
> @@ -341,6 +341,31 @@ int pinctrl_get_group_selector(struct pinctrl_dev *pctldev,
> ?}
>
> ?/**
> + * pinctrl_get_pin_id() - returns the group selector for a group
> + * @pctldev: the pin controller handling the group
> + * @pin_group: the pin group to look up
This kerneldoc is wrong... pin, not group.
> + */
> +int pinctrl_get_pin_id(struct pinctrl_dev *pctldev,
> + ? ? ? ? ? ? ? ? ? ? ?const char *pin)
> +{
> + ? ? ? unsigned int i;
> +
> + ? ? ? for (i = 0; i < pctldev->desc->npins; i++) {
> + ? ? ? ? ? ? ? if (pctldev->desc->pins[i].name == NULL)
> + ? ? ? ? ? ? ? ? ? ? ? continue;
> + ? ? ? ? ? ? ? if (!strcmp(pin, pctldev->desc->pins[i].name)) {
> + ? ? ? ? ? ? ? ? ? ? ? dev_dbg(pctldev->dev, "found pin id %u for %s\n",
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? i, pin);
> + ? ? ? ? ? ? ? ? ? ? ? return i;
> + ? ? ? ? ? ? ? }
> + ? ? ? }
(...)
> ? ? ? ?/* First sanity check the new mapping */
> ? ? ? ?for (i = 0; i < num_maps; i++) {
> + ? ? ? ? ? ? ? if (!maps[i].dev_name) {
> + ? ? ? ? ? ? ? ? ? ? ? pr_err("failed to register map %s (%d): no device given\n",
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?maps[i].name, i);
> + ? ? ? ? ? ? ? ? ? ? ? return -EINVAL;
> + ? ? ? ? ? ? ? }
> +
Hm should this not be done earlier in the patch series?
> + ? ? ? /*
> + ? ? ? ?* FIXME: We should really get the pin controler to dump the config
> + ? ? ? ?* values, so they can be decoded to something meaningful.
> + ? ? ? ?*/
> + ? ? ? for (i = 0; i < setting->data.configs.num_configs; i++)
> + ? ? ? ? ? ? ? seq_printf(s, " %08lx", setting->data.configs.configs[i]);
> +
> + ? ? ? seq_printf(s, "\n");
> +}
Per-device config print function? But no need to rush that.
Apart from this I mostly just trust this patch, like the previous one.
Yours,
Linus Walleij
Dong Aisheng wrote at Wednesday, February 22, 2012 9:48 PM:
> On Wed, Feb 22, 2012 at 07:53:44PM -0800, Stephen Warren wrote:
...
> > I'm hoping that we don't do this internal conversion. The rules I'd like are:
...
> > * Every mapping table entry must include a non-NULL name field.
> >
> > * Every call to pinctrl_get()/pinctrl_lookup_state() must pass a non-NULL name
>
> This is a way.
>
> Before using this, i'm still wondering what big problems do you think for us to support
> a NULL map name?
> Because the name for devices do not have different state really does not make too much
> sense but extra overhead.
If we disallow NULL names, it simplifies the code in the pinctrl core;
when registering mappings or right at the start of pinctrl_get() or
pinctrl_lookup_state(), we check if the name is NULL and if so error out.
Everywhere else can then assume name!=NULL, and hence not have special-
cases for name==NULL, e.g.:
In debug code:
name ? name : "(unnamed)"
vs.:
name
When matching mapping table entries:
match = !name ? !map->name : !strcmp(name, map->name)
vs.:
match = !strcmp(name, map->name)
Similar for the body of pinctrl_lookup_state().
Equally, it's not possible to generate a mapping table entry with a NULL
name from device tree given the bindings we discussed, so disallowing them
everywhere keeps things consistent.
--
nvpublic
Linus Walleij wrote at Wednesday, February 22, 2012 10:55 PM:
> On Mon, Feb 20, 2012 at 7:45 AM, Stephen Warren <[email protected]> wrote:
...
> This is looking real good. I think recent discussion with Russell
> also ironed out the problems with potential gpio interaction.
Hmm. I guess I need to go re-read that then; my impression was that we
hadn't really reached a solid conclusion yet.
...
> Please move this patch as far to the head of the series as possible
> so we can get it in, I guess you need the state lookup in struct pinctrl
> to proceed but could we e.g. puy the locking changes after this?
The main reason I wrote the patches like the locking patch was due to
issues I found when working on these two main patches. I'm not sure that
these later patches would work completely correctly without the locking
rework first...
--
nvpublic
Linus Walleij wrote at Wednesday, February 22, 2012 11:09 PM:
> On Mon, Feb 20, 2012 at 7:46 AM, Stephen Warren <[email protected]> wrote:
...
> > @@ -1022,7 +1074,7 @@ Since it may be common to request the core to hog a few always-applicable
> > ?mux settings on the primary pin controller, there is a convenience macro for
> > ?this:
> >
> > -PIN_MAP_SYS_HOG("active", "pinctrl-foo", "power_func")
> > +PIN_MAP_MUX_GROUP("pinctrl-foo", "active", "pinctrl-foo", NULL, "power_func")
>
> Please keep the explicit _HOG macros for readability. Relying on
> the implicit relation between dev and pctldev being the same and to be
> parsed by humans is vulnerable.
>
> PIN_MAP_MUX_GROUP_HOG()
OK, I guess I can add some of those back. The main reason I removed the
special-cases was to avoid consumer.h being chock full of a ton of
different macros you had to choose from. This wasn't so much of an issue
before, but since the number of macros has grown now to support pin
config, dummy states, etc., it seemed cluttered.
Still, I guess they're useful, so I can add them back since you asked.
--
nvpublic
Linus Walleij wrote at Wednesday, February 22, 2012 11:09 PM:
> On Mon, Feb 20, 2012 at 7:46 AM, Stephen Warren <[email protected]> wrote:
> > The pinctrl mapping table can now contain entries to:
> > * Set the mux function of a pin group
> > * Apply a set of pin config options to a pin or a group
> >
> > This allows pinctrl_select_state() to apply pin configs settings as well
> > as mux settings.
> >
> > Signed-off-by: Stephen Warren <[email protected]>
...
> > ? ? ? ?/* First sanity check the new mapping */
> > ? ? ? ?for (i = 0; i < num_maps; i++) {
> > + ? ? ? ? ? ? ? if (!maps[i].dev_name) {
> > + ? ? ? ? ? ? ? ? ? ? ? pr_err("failed to register map %s (%d): no device given\n",
> > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?maps[i].name, i);
> > + ? ? ? ? ? ? ? ? ? ? ? return -EINVAL;
> > + ? ? ? ? ? ? ? }
> > +
>
> Hm should this not be done earlier in the patch series?
This patch isn't adding that check, it's just moving it a little earlier
in the same block.
The old code checked everything required for "MUX_GROUP" type mapping
table entries, but in the new code not all those same checks exist for
every type of mapping entry. I just moved all the common stuff to the
top of the block in one common place, followed by the stuff that varies.
So, I think that chunk is OK.
--
nvpublic
On Thu, Feb 23, 2012 at 08:39:58AM -0800, Stephen Warren wrote:
> Dong Aisheng wrote at Wednesday, February 22, 2012 9:48 PM:
> > On Wed, Feb 22, 2012 at 07:53:44PM -0800, Stephen Warren wrote:
> ...
> > > I'm hoping that we don't do this internal conversion. The rules I'd like are:
> ...
> > > * Every mapping table entry must include a non-NULL name field.
> > >
> > > * Every call to pinctrl_get()/pinctrl_lookup_state() must pass a non-NULL name
> >
> > This is a way.
> >
> > Before using this, i'm still wondering what big problems do you think for us to support
> > a NULL map name?
> > Because the name for devices do not have different state really does not make too much
> > sense but extra overhead.
>
> If we disallow NULL names, it simplifies the code in the pinctrl core;
> when registering mappings or right at the start of pinctrl_get() or
> pinctrl_lookup_state(), we check if the name is NULL and if so error out.
> Everywhere else can then assume name!=NULL, and hence not have special-
> cases for name==NULL, e.g.:
>
> In debug code:
> name ? name : "(unnamed)"
> vs.:
> name
>
> When matching mapping table entries:
> match = !name ? !map->name : !strcmp(name, map->name)
> vs.:
> match = !strcmp(name, map->name)
>
> Similar for the body of pinctrl_lookup_state().
>
Yes, it does make thing simple.
But i guess it's not the key point to not support NULL state name, right?
> Equally, it's not possible to generate a mapping table entry with a NULL
> name from device tree given the bindings we discussed, so disallowing them
> everywhere keeps things consistent.
>
Yes, i'm wondering if we can change it a bit to support NULL name.
I replied with my idea in another mail before this one.
Regards
Dong Aisheng
On Mon, Feb 20, 2012 at 2:45 PM, Stephen Warren <[email protected]> wrote:
> This change separates two aspects of struct pinctrl:
>
> a) The data representation of the parsed mapping table, into:
>
> ? 1) The top-level struct pinctrl object, a single entity returned
> ? ? ?by pinctrl_get().
>
> ? 2) The parsed version of each mapping table entry, struct
> ? ? ?pinctrl_setting, of which there is one per mapping table entry.
>
> b) The code that handles this; the code for (1) above is in core.c, and
> ? the code to parse/execute each entry in (2) above is in pinmux.c, while
> ? the iteration over multiple settings is lifted to core.c.
>
> This will allow the following future changes:
>
> 1) pinctrl_get() API rework, so that struct pinctrl represents all states
> ? for the device, and the device can select between them without calling
> ? put()/get() again.
>
> 2) To support that, a struct pinctrl_state object will be inserted into
> ? the data model between the struct pinctrl and struct pinctrl_setting.
>
> 3) The mapping table will be extended to allow specification of pin config
> ? settings too. To support this, struct pinctrl_setting will be enhanced
> ? to store either mux settings or config settings, and functions will be
> ? added to pinconf.c to parse/execute pin configuration settings.
>
> Signed-off-by: Stephen Warren <[email protected]>
Looks good to me.
Please also with my tag.
Acked-by: Dong Aisheng <[email protected]>
BTW, one minor thing, see below:
...
> -/**
> - * pinmux_search_function() - check pin control driver for a certain function
> - * @pctldev: device to check for function and position
> - * @map: function map containing the function and position to look for
> - * @func_selector: returns the applicable function selector if found
> - * @group_selector: returns the applicable group selector if found
> - *
> - * This will search the pinmux driver for an applicable
> - * function with a specific pin group, returns 0 if these can be mapped
> - * negative otherwise
> - */
> -static int pinmux_search_function(struct pinctrl_dev *pctldev,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct pinctrl_map const *map,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? unsigned *func_selector,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? unsigned *group_selector)
> +int pinmux_func_name_to_selector(struct pinctrl_dev *pctldev,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?const char *function)
Static?
Regards
Dong Aisheng
On Sun, Feb 19, 2012 at 11:45:57PM -0700, Stephen Warren wrote:
> Multiple mapping table entries could reference the same pin, and hence
> "own" it. This would be unusual now that pinctrl_get() represents a single
> state for a client device, but in the future when it represents all known
> states for a device, this is quite likely. Implement reference counting
> for pin ownership to handle this.
>
> Signed-off-by: Stephen Warren <[email protected]>
> /*
> - * If there is no kind of request function for the pin we just assume
> - * we got it by default and proceed.
> - */
> + * If there is no kind of request function for the pin we just assume
> + * we got it by default and proceed.
> + */
I remember the correct format for multiple lines of comments is:
/*
* ...
*/
But i see the changes here are(i'm using mutt):
/*
* ...
*/
Can you help explain?
Else please also take my ACK:
Acked-by: Dong Aisheng <[email protected]>
Regards
Dong Aisheng
On Sun, Feb 19, 2012 at 11:45:59PM -0700, Stephen Warren wrote:
> The API model is changed from:
>
> p = pinctrl_get(dev, "state1");
> pinctrl_enable(p);
> ...
> pinctrl_disable(p);
> pinctrl_put(p);
> p = pinctrl_get(dev, "state2");
> pinctrl_enable(p);
> ...
> pinctrl_disable(p);
> pinctrl_put(p);
>
> to this:
>
> p = pinctrl_get(dev);
> s1 = pinctrl_lookup_state(p, "state1");
> s2 = pinctrl_lookup_state(p, "state2");
> pinctrl_select_state(p, s1);
> ...
> pinctrl_select_state(p, s2);
> ...
> pinctrl_put(p);
>
> This allows devices to directly transition between states without
> disabling the pin controller programming and put()/get()ing the
> configuration data each time. This model will also better suit pinconf
> programming, which doesn't have a concept of "disable".
>
It's exactly what we discussed and wanted.
Thank for the great and hard work.
> The special-case hogging feature of pin controllers is re-written to use
> the regular APIs instead of special-case code. Hence, the pinmux-hogs
> debugfs file is removed; see the top-level pinctrl-handles files for
> equivalent data.
>
> Signed-off-by: Stephen Warren <[email protected]>
> ---
> Documentation/pinctrl.txt | 153 ++++++++-----
> arch/arm/mach-u300/core.c | 28 +--
> drivers/pinctrl/core.c | 491 +++++++++++++++++--------------------
> drivers/pinctrl/core.h | 24 ++-
> drivers/tty/serial/sirfsoc_uart.c | 12 +-
> include/linux/pinctrl/consumer.h | 55 ++++-
> include/linux/pinctrl/machine.h | 21 +-
> 7 files changed, 408 insertions(+), 376 deletions(-)
>
>
> @@ -814,7 +817,7 @@ it even more compact which assumes you want to use pinctrl-foo and position
> 0 for mapping, for example:
>
> static struct pinctrl_map __initdata mapping[] = {
> - PIN_MAP("I2CMAP", "pinctrl-foo", "i2c0", "foo-i2c.0"),
> + PIN_MAP("default", "pinctrl-foo", "i2c0", "foo-i2c.0"),
I remember you said you will also change the PIN_MAP sequence that
place the device name at first.
Will see your further patch.
> The result of grabbing this mapping from the device with something like
> this (see next paragraph):
>
> - p = pinctrl_get(&device, "8bit");
> + p = pinctrl_get(dev);
> + s = pinctrl_lookup_state(p, "8bit");
> + ret = pinctrl_select_state(p, s);
> +
> +or more simply:
> +
> + p = pinctrl_get_select(dev, "8bit");
>
Very glad to see this simply one. :-)
> foo_probe()
> {
> - /* Allocate a state holder named "state" etc */
> - struct pinctrl p;
> + /* Allocate a state holder named "foo" etc */
> + struct foo_state *foo = ...;
>
> - p = pinctrl_get(&device, "default");
> - if IS_ERR(p)
> - return PTR_ERR(p);
> - pinctrl_enable(p);
> + foo->p = pinctrl_get(&device);
> + if (IS_ERR(foo->p)) {
> + /* FIXME: clean up "foo" here */
> + return PTR_ERR(foo->p);
> + }
> +
> + foo->s = pinctrl_lookup_state(foo->p, "default");
> + if (IS_ERR(foo->s)) {
> + pinctrl_put(foo->p);
> + /* FIXME: clean up "foo" here */
> + return PTR_ERR(s);
> + }
>
> - state->p = p;
> + ret = pinctrl_select_state(s);
s/s/foo->s
> @@ -976,25 +1004,25 @@ System pin control hogging
> ==========================
>
> Pin control map entries can be hogged by the core when the pin controller
> -is registered. This means that the core will attempt to call pinctrl_get() and
> -pinctrl_enable() on it immediately after the pin control device has been
> -registered.
> +is registered. This means that the core will attempt to call pinctrl_get(),
> +lookup_state() and select_state() on it immediately after the pin control
> +device has been registered.
>
> -This is enabled by simply setting the .dev_name field in the map to the name
> -of the pin controller itself, like this:
> +This occurs for mapping table entries where the client device name is equal
> +to the pin controller device name, and the state name is "active".
>
> {
> - .name = "POWERMAP"
> + .dev_name = "pinctrl-foo",
> + .name = "active",
I guess if we really decide to use a fixed state name for hog functions,
we'd better not let users to write the state name, at least provide a macro.
> .ctrl_dev_name = "pinctrl-foo",
> .function = "power_func",
> - .dev_name = "pinctrl-foo",
> },
>
> Since it may be common to request the core to hog a few always-applicable
> mux settings on the primary pin controller, there is a convenience macro for
> this:
>
> -PIN_MAP_SYS_HOG("POWERMAP", "pinctrl-foo", "power_func")
> +PIN_MAP_SYS_HOG("active", "pinctrl-foo", "power_func")
I remember you had a patch changing this macro a bit.
So here may also need change.
> +static struct pinctrl *find_pinctrl(struct device *dev)
> +{
> + struct pinctrl *p;
>
> - dev_dbg(dev, "pinctrl_get() for state %s\n", name);
> + list_for_each_entry(p, &pinctrldev_list, node)
s/pinctrldev_list/pinctrl_list ?
> +static struct pinctrl *pinctrl_get_locked(struct device *dev)
> +{
> + struct pinctrl *p;
>
> -error:
> - list_for_each_entry(setting, &p->settings, node)
> - pinmux_free_setting(setting);
> + if (WARN_ON(!dev))
> + return ERR_PTR(-EINVAL);
>
> - kfree(p);
> + p = find_pinctrl(dev);
> + if (p == NULL)
> + p = create_pinctrl(dev);
> + if (IS_ERR(p))
> + return p;
> +
> + p->usecount++;
I still can not understand what's the purpose of p->usecount?
For allowing multi times calling of pinctrl_get for on the same device?
> +static inline struct pinctrl * __must_check pinctrl_get_select(
> + struct device *dev, const char *name)
> +{
> + struct pinctrl *p;
> + struct pinctrl_state *s;
> + int ret;
> +
> + p = pinctrl_get(dev);
> + if (IS_ERR(p))
> + return p;
> +
> + s = pinctrl_lookup_state(p, name);
> + if (IS_ERR(s)) {
> + pinctrl_put(p);
> + return ERR_PTR(PTR_ERR(s));
> + }
> +
> + ret = pinctrl_select_state(p, s);
> + if (ret < 0) {
> + pinctrl_put(p);
> + return ERR_PTR(ret);
s/ERR_PTR(ret)/ret ?
Regards
Dong Aisheng
On Sun, Feb 19, 2012 at 11:46:00PM -0700, Stephen Warren wrote:
> The pinctrl mapping table can now contain entries to:
> * Set the mux function of a pin group
> * Apply a set of pin config options to a pin or a group
>
> This allows pinctrl_select_state() to apply pin configs settings as well
> as mux settings.
>
> Signed-off-by: Stephen Warren <[email protected]>
....
> - PIN_MAP("default", "pinctrl-foo", "i2c0", "foo-i2c.0"),
> + PIN_MAP_MUX_GROUP("foo-i2c.o", "default", "pinctrl-foo", NULL, "i2c0"),
> +};
> +
> +The mapping table may also contain pin configuration entries. It's common for
> +each pin/group to have a number of configuration entries that affect it, so
> +the table entries for configuration reference an array of config parameters
> +and values. An example using the convenience macros is shown below:
> +
> +static unsigned long i2c_grp_configs[] = {
> + FOO_PIN_DRIVEN,
> + FOO_PIN_PULLUP,
> +};
> +
> +static unsigned long i2c_pin_configs[] = {
> + FOO_OPEN_COLLECTOR,
> + FOO_SLEW_RATE_SLOW,
> +};
> +
> +static struct pinctrl_map __initdata mapping[] = {
> + PIN_MAP_MUX_GROUP("foo-i2c.0", "default", "pinctrl-foo", "i2c0", "i2c0"),
> + PIN_MAP_MUX_CONFIGS_GROUP("foo-i2c.0", "default", "pinctrl-foo", "i2c0", i2c_grp_configs),
> + PIN_MAP_MUX_CONFIGS_PIN("foo-i2c.0", "default", "pinctrl-foo", "i2c0scl", i2c_pin_configs),
> + PIN_MAP_MUX_CONFIGS_PIN("foo-i2c.0", "default", "pinctrl-foo", "i2c0sda", i2c_pin_configs),
I still have not read all over this patch.
But one question i'm considering is that
will this way here also work for "virtual" group?
For example, the virtual group "i2c_grp_configs" may actually contains
the config for each pin in that group?
The core will handle this difference or let each driver to handle it?
> @@ -1022,7 +1074,7 @@ Since it may be common to request the core to hog a few always-applicable
> mux settings on the primary pin controller, there is a convenience macro for
> this:
>
> -PIN_MAP_SYS_HOG("active", "pinctrl-foo", "power_func")
Hmm?
Why remove this one?
> +PIN_MAP_MUX_GROUP("pinctrl-foo", "active", "pinctrl-foo", NULL, "power_func")
>
> This gives the exact same result as the above construction.
>
> diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c
> index eb79a49..599aa79 100644
> --- a/arch/arm/mach-u300/core.c
> +++ b/arch/arm/mach-u300/core.c
> @@ -1554,13 +1554,13 @@ static struct platform_device pinmux_device = {
> /* Pinmux settings */
> static struct pinctrl_map __initdata u300_pinmux_map[] = {
> /* anonymous maps for chip power and EMIFs */
> - PIN_MAP_SYS_HOG("default", "pinmux-u300", "power"),
> - PIN_MAP_SYS_HOG("default", "pinmux-u300", "emif0"),
> - PIN_MAP_SYS_HOG("default", "pinmux-u300", "emif1"),
> + PIN_MAP_MUX_GROUP("pinmux-u300", "default", "pinmux-u300", NULL, "power"),
> + PIN_MAP_MUX_GROUP("pinmux-u300", "default", "pinmux-u300", NULL, "emif0"),
> + PIN_MAP_MUX_GROUP("pinmux-u300", "default", "pinmux-u300", NULL, "emif1"),
> /* per-device maps for MMC/SD, SPI and UART */
> - PIN_MAP("default", "pinmux-u300", "mmc0", "mmci"),
> - PIN_MAP("default", "pinmux-u300", "spi0", "pl022"),
> - PIN_MAP("default", "pinmux-u300", "uart0", "uart0"),
> + PIN_MAP_MUX_GROUP("mmci", "default", "pinmux-u300", NULL, "mmc0"),
> + PIN_MAP_MUX_GROUP("pl022", "default", "pinmux-u300", NULL, "spi0"),
> + PIN_MAP_MUX_GROUP("uart0", "default", "pinmux-u300", NULL, "uart0"),
> };
>
> struct u300_mux_hog {
> diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
> index bab1a69..af4ebe9 100644
> --- a/drivers/pinctrl/core.c
> +++ b/drivers/pinctrl/core.c
> @@ -341,6 +341,31 @@ int pinctrl_get_group_selector(struct pinctrl_dev *pctldev,
> }
>
> /**
> + * pinctrl_get_pin_id() - returns the group selector for a group
> + * @pctldev: the pin controller handling the group
> + * @pin_group: the pin group to look up
The comment seems not correct here.
> + */
> +int pinctrl_get_pin_id(struct pinctrl_dev *pctldev,
> + const char *pin)
> +{
> + unsigned int i;
> +
> + for (i = 0; i < pctldev->desc->npins; i++) {
> + if (pctldev->desc->pins[i].name == NULL)
> + continue;
> + if (!strcmp(pin, pctldev->desc->pins[i].name)) {
> + dev_dbg(pctldev->dev, "found pin id %u for %s\n",
> + i, pin);
> + return i;
It looks actually this is not a PIN id.
It's just the index of the pin array.
Pin has its own id:
struct pinctrl_pin_desc {
unsigned number;
const char *name;
};
> static int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
> unsigned long *config)
> {
> @@ -260,8 +278,154 @@ unlock:
> }
> EXPORT_SYMBOL(pin_config_group_set);
>
> +int pinconf_map_to_setting(struct pinctrl_map const *map,
> + struct pinctrl_setting *setting)
> +{
> + struct pinctrl_dev *pctldev = setting->pctldev;
> +
> + switch (setting->type) {
> + case PIN_MAP_TYPE_CONFIGS_PIN:
> + setting->data.configs.group_or_pin =
> + pinctrl_get_pin_id(pctldev,
> + map->data.configs.group_or_pin);
> + if (setting->data.configs.group_or_pin < 0)
> + return setting->data.configs.group_or_pin;
> + break;
> + break;
Two break here.
Regards
Dong Aisheng
Dong Aisheng wrote at Monday, February 27, 2012 12:12 AM:
> On Sun, Feb 19, 2012 at 11:45:57PM -0700, Stephen Warren wrote:
> > Multiple mapping table entries could reference the same pin, and hence
> > "own" it. This would be unusual now that pinctrl_get() represents a single
> > state for a client device, but in the future when it represents all known
> > states for a device, this is quite likely. Implement reference counting
> > for pin ownership to handle this.
> >
> > Signed-off-by: Stephen Warren <[email protected]>
...
> > /*
> > - * If there is no kind of request function for the pin we just assume
> > - * we got it by default and proceed.
> > - */
> > + * If there is no kind of request function for the pin we just assume
> > + * we got it by default and proceed.
> > + */
>
> I remember the correct format for multiple lines of comments is:
> /*
> * ...
> */
>
> But i see the changes here are(i'm using mutt):
> /*
> * ...
> */
> Can you help explain?
It was a mistake; my editor corrupted it when I added or removed some
indentation levels. I noticed this and fixed it locally when doing
some rebasing.
> Else please also take my ACK:
> Acked-by: Dong Aisheng <[email protected]>
Thanks.
--
nvpublic
Dong Aisheng wrote at Monday, February 27, 2012 2:07 AM:
> On Sun, Feb 19, 2012 at 11:45:59PM -0700, Stephen Warren wrote:
> > - .name = "POWERMAP"
> > + .dev_name = "pinctrl-foo",
> > + .name = "active",
>
> I guess if we really decide to use a fixed state name for hog functions,
> we'd better not let users to write the state name, at least provide a macro.
Yes, that's a good point for adding the special-case macros. I have
added such special-case macros to my local version of patch 20, so they'll
be there in the repost.
> > +static struct pinctrl *pinctrl_get_locked(struct device *dev)
> > +{
> > + struct pinctrl *p;
> >
> > -error:
> > - list_for_each_entry(setting, &p->settings, node)
> > - pinmux_free_setting(setting);
> > + if (WARN_ON(!dev))
> > + return ERR_PTR(-EINVAL);
> >
> > - kfree(p);
> > + p = find_pinctrl(dev);
> > + if (p == NULL)
> > + p = create_pinctrl(dev);
> > + if (IS_ERR(p))
> > + return p;
> > +
> > + p->usecount++;
>
> I still can not understand what's the purpose of p->usecount?
> For allowing multi times calling of pinctrl_get for on the same device?
pinctrl_get() could be called multiple times for the same device. Rather
than create a whole new struct pinctrl each time it's called, we just
reference count the object so that each call returns the same one, and
it won't be destroyed until all users have called pinctrl_put().
Hopefully it is true that multiple different pieces of code won't be
screwing with the same device's pinctrl settings, but it's simple enough
to do this so we may as well. This somewhat of a the moral equivalent of
the old code's p->usecount manipulations in pinctrl_enable()/disable(),
although admittedly a little different.
> > +static inline struct pinctrl * __must_check pinctrl_get_select(
> > + struct device *dev, const char *name)
> > +{
> > + struct pinctrl *p;
> > + struct pinctrl_state *s;
> > + int ret;
> > +
> > + p = pinctrl_get(dev);
> > + if (IS_ERR(p))
> > + return p;
> > +
> > + s = pinctrl_lookup_state(p, name);
> > + if (IS_ERR(s)) {
> > + pinctrl_put(p);
> > + return ERR_PTR(PTR_ERR(s));
> > + }
> > +
> > + ret = pinctrl_select_state(p, s);
> > + if (ret < 0) {
> > + pinctrl_put(p);
> > + return ERR_PTR(ret);
>
> s/ERR_PTR(ret)/ret ?
The function returns a pointer, whereas ret is an int. ERR_PTR() is used
to wrap the int error code into a pointer value so that the function can
return either a valid pointer, or an error-code. See include/linux/err.h.
I've fixed locally up the other issues you pointed out. Thanks.
--
nvpublic
Dong Aisheng wrote at Monday, February 27, 2012 5:21 AM:
> On Sun, Feb 19, 2012 at 11:46:00PM -0700, Stephen Warren wrote:
> > The pinctrl mapping table can now contain entries to:
> > * Set the mux function of a pin group
> > * Apply a set of pin config options to a pin or a group
> >
> > This allows pinctrl_select_state() to apply pin configs settings as well
> > as mux settings.
> >
> > Signed-off-by: Stephen Warren <[email protected]>
...
> > +The mapping table may also contain pin configuration entries. It's common for
> > +each pin/group to have a number of configuration entries that affect it, so
> > +the table entries for configuration reference an array of config parameters
> > +and values. An example using the convenience macros is shown below:
> > +
> > +static unsigned long i2c_grp_configs[] = {
> > + FOO_PIN_DRIVEN,
> > + FOO_PIN_PULLUP,
> > +};
> > +
> > +static unsigned long i2c_pin_configs[] = {
> > + FOO_OPEN_COLLECTOR,
> > + FOO_SLEW_RATE_SLOW,
> > +};
> > +
> > +static struct pinctrl_map __initdata mapping[] = {
> > + PIN_MAP_MUX_GROUP("foo-i2c.0", "default", "pinctrl-foo", "i2c0", "i2c0"),
> > + PIN_MAP_MUX_CONFIGS_GROUP("foo-i2c.0", "default", "pinctrl-foo", "i2c0", i2c_grp_configs),
> > + PIN_MAP_MUX_CONFIGS_PIN("foo-i2c.0", "default", "pinctrl-foo", "i2c0scl", i2c_pin_configs),
> > + PIN_MAP_MUX_CONFIGS_PIN("foo-i2c.0", "default", "pinctrl-foo", "i2c0sda", i2c_pin_configs),
>
> I still have not read all over this patch.
> But one question i'm considering is that
> will this way here also work for "virtual" group?
> For example, the virtual group "i2c_grp_configs" may actually contains
> the config for each pin in that group?
> The core will handle this difference or let each driver to handle it?
Since the core has no knowledge of virtual groups, everything has to be
handled inside the pin controller driver: When the core asks the driver
to enumerate the groups it supports, those virtual groups must be included
in the list. The mapping table may contain entries to configure those
virtual groups, which will be passed on to the driver to implement as it
sees fit. So, in short, yes, I believe this handles virtual groups just
fine.
> > @@ -1022,7 +1074,7 @@ Since it may be common to request the core to hog a few always-applicable
> > mux settings on the primary pin controller, there is a convenience macro for
> > this:
> >
> > -PIN_MAP_SYS_HOG("active", "pinctrl-foo", "power_func")
>
> Hmm?
> Why remove this one?
In the patch I posted, I simplified the mapping table macros by replacing
all mux entries with a single macro PIN_MAP_MUX_GROUP(). However, I've
since modified the patch to include a number of special-case macros, so
this macro has been added back (albeit under a slightly different name).
> > +int pinctrl_get_pin_id(struct pinctrl_dev *pctldev,
> > + const char *pin)
> > +{
> > + unsigned int i;
> > +
> > + for (i = 0; i < pctldev->desc->npins; i++) {
> > + if (pctldev->desc->pins[i].name == NULL)
> > + continue;
> > + if (!strcmp(pin, pctldev->desc->pins[i].name)) {
> > + dev_dbg(pctldev->dev, "found pin id %u for %s\n",
> > + i, pin);
> > + return i;
>
> It looks actually this is not a PIN id.
> It's just the index of the pin array.
> Pin has its own id:
> struct pinctrl_pin_desc {
> unsigned number;
> const char *name;
> };
I guess I should just delete this function and call pin_get_from_name()
instead.
However, this does raise one question:
Right now, pin_config_set() calls pin_get_from_name() to find the pin
ID of a pin. This returns that "number" field in the struct above. This
is then passed to the pin controller driver's pin_config_set() callback.
Hence, the pin ID value passed to pin_config_set() can't be used to index
into the driver's own pin_desc array if the pin numbers are sparse. Is
that intended? I suppose it's OK since any driver-specific information
about each pin can't be stored in the pin_desc array anyway, since that
array has a standard type without space for driver-specific data, and
any driver-specific array would probably be indexed by the values in the
.number field, not the pin_desc array index.
Thanks.
--
nvpublic
On Mon, Feb 27, 2012 at 10:37:16AM -0800, Stephen Warren wrote:
> Dong Aisheng wrote at Monday, February 27, 2012 2:07 AM:
> > On Sun, Feb 19, 2012 at 11:45:59PM -0700, Stephen Warren wrote:
..........
>
> > > +static struct pinctrl *pinctrl_get_locked(struct device *dev)
> > > +{
> > > + struct pinctrl *p;
> > >
> > > -error:
> > > - list_for_each_entry(setting, &p->settings, node)
> > > - pinmux_free_setting(setting);
> > > + if (WARN_ON(!dev))
> > > + return ERR_PTR(-EINVAL);
> > >
> > > - kfree(p);
> > > + p = find_pinctrl(dev);
> > > + if (p == NULL)
> > > + p = create_pinctrl(dev);
> > > + if (IS_ERR(p))
> > > + return p;
> > > +
> > > + p->usecount++;
> >
> > I still can not understand what's the purpose of p->usecount?
> > For allowing multi times calling of pinctrl_get for on the same device?
>
> pinctrl_get() could be called multiple times for the same device. Rather
> than create a whole new struct pinctrl each time it's called, we just
> reference count the object so that each call returns the same one, and
> it won't be destroyed until all users have called pinctrl_put().
>
> Hopefully it is true that multiple different pieces of code won't be
> screwing with the same device's pinctrl settings, but it's simple enough
> to do this so we may as well. This somewhat of a the moral equivalent of
> the old code's p->usecount manipulations in pinctrl_enable()/disable(),
> although admittedly a little different.
>
Hmm, yes, a slight difference after looking the old code.
Oringally the pinmux->usecount was introduced to allow nested call of pinmux_enable
(but not pinmux_get since it will return an error due to pin conflicts).
In the new way, you allow nested call of pinctrl_get.
I still can't find in which case the device will have such requirement
since per my understanding pinctrl is a little different from clock
(clock can be used by different devices but we do not allow pins to be
used by difference devices at the same time).
However it's actually another issue which is not related to this patch since
we're just trying to keep align with the old code.
So it's ok to me for you to keep it here first.
> > > +static inline struct pinctrl * __must_check pinctrl_get_select(
> > > + struct device *dev, const char *name)
> > > +{
> > > + struct pinctrl *p;
> > > + struct pinctrl_state *s;
> > > + int ret;
> > > +
> > > + p = pinctrl_get(dev);
> > > + if (IS_ERR(p))
> > > + return p;
> > > +
> > > + s = pinctrl_lookup_state(p, name);
> > > + if (IS_ERR(s)) {
> > > + pinctrl_put(p);
> > > + return ERR_PTR(PTR_ERR(s));
> > > + }
> > > +
> > > + ret = pinctrl_select_state(p, s);
> > > + if (ret < 0) {
> > > + pinctrl_put(p);
> > > + return ERR_PTR(ret);
> >
> > s/ERR_PTR(ret)/ret ?
>
> The function returns a pointer, whereas ret is an int. ERR_PTR() is used
> to wrap the int error code into a pointer value so that the function can
> return either a valid pointer, or an error-code. See include/linux/err.h.
>
Hmm, below is what i see in your patch:
+int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state)
{
+ int ret;
+
mutex_lock(&pinctrl_mutex);
- pinctrl_disable_locked(p);
+ ret = pinctrl_select_state_locked(p, state);
mutex_unlock(&pinctrl_mutex);
+
+ return ret;
}
It seems pinctrl_select_state does not return a pointer.
> I've fixed locally up the other issues you pointed out. Thanks.
>
Great.
Thanks.
Regards
Dong Aisheng
On Mon, Feb 27, 2012 at 11:02:01AM -0800, Stephen Warren wrote:
> Dong Aisheng wrote at Monday, February 27, 2012 5:21 AM:
> > On Sun, Feb 19, 2012 at 11:46:00PM -0700, Stephen Warren wrote:
> > > The pinctrl mapping table can now contain entries to:
> > > * Set the mux function of a pin group
> > > * Apply a set of pin config options to a pin or a group
> > >
> > > This allows pinctrl_select_state() to apply pin configs settings as well
> > > as mux settings.
> > >
> > > Signed-off-by: Stephen Warren <[email protected]>
> ...
> > > +The mapping table may also contain pin configuration entries. It's common for
> > > +each pin/group to have a number of configuration entries that affect it, so
> > > +the table entries for configuration reference an array of config parameters
> > > +and values. An example using the convenience macros is shown below:
> > > +
> > > +static unsigned long i2c_grp_configs[] = {
> > > + FOO_PIN_DRIVEN,
> > > + FOO_PIN_PULLUP,
> > > +};
> > > +
> > > +static unsigned long i2c_pin_configs[] = {
> > > + FOO_OPEN_COLLECTOR,
> > > + FOO_SLEW_RATE_SLOW,
> > > +};
> > > +
> > > +static struct pinctrl_map __initdata mapping[] = {
> > > + PIN_MAP_MUX_GROUP("foo-i2c.0", "default", "pinctrl-foo", "i2c0", "i2c0"),
> > > + PIN_MAP_MUX_CONFIGS_GROUP("foo-i2c.0", "default", "pinctrl-foo", "i2c0", i2c_grp_configs),
> > > + PIN_MAP_MUX_CONFIGS_PIN("foo-i2c.0", "default", "pinctrl-foo", "i2c0scl", i2c_pin_configs),
> > > + PIN_MAP_MUX_CONFIGS_PIN("foo-i2c.0", "default", "pinctrl-foo", "i2c0sda", i2c_pin_configs),
> >
> > I still have not read all over this patch.
> > But one question i'm considering is that
> > will this way here also work for "virtual" group?
> > For example, the virtual group "i2c_grp_configs" may actually contains
> > the config for each pin in that group?
> > The core will handle this difference or let each driver to handle it?
>
> Since the core has no knowledge of virtual groups, everything has to be
> handled inside the pin controller driver: When the core asks the driver
> to enumerate the groups it supports, those virtual groups must be included
> in the list. The mapping table may contain entries to configure those
> virtual groups, which will be passed on to the driver to implement as it
> sees fit. So, in short, yes, I believe this handles virtual groups just
> fine.
>
Ok, great.
> > > @@ -1022,7 +1074,7 @@ Since it may be common to request the core to hog a few always-applicable
> > > mux settings on the primary pin controller, there is a convenience macro for
> > > this:
> > >
> > > -PIN_MAP_SYS_HOG("active", "pinctrl-foo", "power_func")
> >
> > Hmm?
> > Why remove this one?
>
> In the patch I posted, I simplified the mapping table macros by replacing
> all mux entries with a single macro PIN_MAP_MUX_GROUP(). However, I've
> since modified the patch to include a number of special-case macros, so
> this macro has been added back (albeit under a slightly different name).
>
Sounds good.
> > > +int pinctrl_get_pin_id(struct pinctrl_dev *pctldev,
> > > + const char *pin)
> > > +{
> > > + unsigned int i;
> > > +
> > > + for (i = 0; i < pctldev->desc->npins; i++) {
> > > + if (pctldev->desc->pins[i].name == NULL)
> > > + continue;
> > > + if (!strcmp(pin, pctldev->desc->pins[i].name)) {
> > > + dev_dbg(pctldev->dev, "found pin id %u for %s\n",
> > > + i, pin);
> > > + return i;
> >
> > It looks actually this is not a PIN id.
> > It's just the index of the pin array.
> > Pin has its own id:
> > struct pinctrl_pin_desc {
> > unsigned number;
> > const char *name;
> > };
>
> I guess I should just delete this function and call pin_get_from_name()
> instead.
>
> However, this does raise one question:
>
> Right now, pin_config_set() calls pin_get_from_name() to find the pin
> ID of a pin. This returns that "number" field in the struct above. This
> is then passed to the pin controller driver's pin_config_set() callback.
> Hence, the pin ID value passed to pin_config_set() can't be used to index
> into the driver's own pin_desc array if the pin numbers are sparse. Is
> that intended? I suppose it's OK since any driver-specific information
> about each pin can't be stored in the pin_desc array anyway, since that
> array has a standard type without space for driver-specific data, and
> any driver-specific array would probably be indexed by the values in the
> .number field, not the pin_desc array index.
It's indeed.
Regards
Dong Aisheng
Dong Aisheng wrote at Monday, February 27, 2012 8:19 PM:
> On Mon, Feb 27, 2012 at 10:37:16AM -0800, Stephen Warren wrote:
> > Dong Aisheng wrote at Monday, February 27, 2012 2:07 AM:
> > > On Sun, Feb 19, 2012 at 11:45:59PM -0700, Stephen Warren wrote:
> ..........
> >
> > > > +static struct pinctrl *pinctrl_get_locked(struct device *dev)
> > > > +{
> > > > + struct pinctrl *p;
> > > >
> > > > -error:
> > > > - list_for_each_entry(setting, &p->settings, node)
> > > > - pinmux_free_setting(setting);
> > > > + if (WARN_ON(!dev))
> > > > + return ERR_PTR(-EINVAL);
> > > >
> > > > - kfree(p);
> > > > + p = find_pinctrl(dev);
> > > > + if (p == NULL)
> > > > + p = create_pinctrl(dev);
> > > > + if (IS_ERR(p))
> > > > + return p;
> > > > +
> > > > + p->usecount++;
> > >
> > > I still can not understand what's the purpose of p->usecount?
> > > For allowing multi times calling of pinctrl_get for on the same device?
> >
> > pinctrl_get() could be called multiple times for the same device. Rather
> > than create a whole new struct pinctrl each time it's called, we just
> > reference count the object so that each call returns the same one, and
> > it won't be destroyed until all users have called pinctrl_put().
...
> I still can't find in which case the device will have such requirement
> since per my understanding pinctrl is a little different from clock
> (clock can be used by different devices but we do not allow pins to be
> used by difference devices at the same time).
True. It's actually very easy to make pinctrl_get() fail if a struct
pinctrl was already created for the device in question. If we do that,
we can completely remove the usecount field. I'll update my patch to do
that.
> > > > +static inline struct pinctrl * __must_check pinctrl_get_select(
> > > > + struct device *dev, const char *name)
> > > > +{
> > > > + struct pinctrl *p;
> > > > + struct pinctrl_state *s;
> > > > + int ret;
> > > > +
> > > > + p = pinctrl_get(dev);
> > > > + if (IS_ERR(p))
> > > > + return p;
> > > > +
> > > > + s = pinctrl_lookup_state(p, name);
> > > > + if (IS_ERR(s)) {
> > > > + pinctrl_put(p);
> > > > + return ERR_PTR(PTR_ERR(s));
> > > > + }
> > > > +
> > > > + ret = pinctrl_select_state(p, s);
> > > > + if (ret < 0) {
> > > > + pinctrl_put(p);
> > > > + return ERR_PTR(ret);
> > >
> > > s/ERR_PTR(ret)/ret ?
> >
> > The function returns a pointer, whereas ret is an int. ERR_PTR() is used
> > to wrap the int error code into a pointer value so that the function can
> > return either a valid pointer, or an error-code. See include/linux/err.h.
>
> Hmm, below is what i see in your patch:
> +int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state)
> {
> + int ret;
> +
> mutex_lock(&pinctrl_mutex);
> - pinctrl_disable_locked(p);
> + ret = pinctrl_select_state_locked(p, state);
> mutex_unlock(&pinctrl_mutex);
> +
> + return ret;
> }
>
> It seems pinctrl_select_state does not return a pointer.
pinctrl_select()_state() returns an int error code.
pinctrl_get_select() returns a pointer, or an error code encoded into a
pointer.
ERR_PTR(ret) is used to convert pinctrl_select()'s int error code into
a pointer representation of the error code for pinctrl_get_select() to
return.
--
nvpublic
On Tue, Feb 28, 2012 at 09:04:10AM -0800, Stephen Warren wrote:
> Dong Aisheng wrote at Monday, February 27, 2012 8:19 PM:
> > On Mon, Feb 27, 2012 at 10:37:16AM -0800, Stephen Warren wrote:
> > > Dong Aisheng wrote at Monday, February 27, 2012 2:07 AM:
> > > > On Sun, Feb 19, 2012 at 11:45:59PM -0700, Stephen Warren wrote:
> > ..........
> > >
> > > > > +static struct pinctrl *pinctrl_get_locked(struct device *dev)
> > > > > +{
> > > > > + struct pinctrl *p;
> > > > >
> > > > > -error:
> > > > > - list_for_each_entry(setting, &p->settings, node)
> > > > > - pinmux_free_setting(setting);
> > > > > + if (WARN_ON(!dev))
> > > > > + return ERR_PTR(-EINVAL);
> > > > >
> > > > > - kfree(p);
> > > > > + p = find_pinctrl(dev);
> > > > > + if (p == NULL)
> > > > > + p = create_pinctrl(dev);
> > > > > + if (IS_ERR(p))
> > > > > + return p;
> > > > > +
> > > > > + p->usecount++;
> > > >
> > > > I still can not understand what's the purpose of p->usecount?
> > > > For allowing multi times calling of pinctrl_get for on the same device?
> > >
> > > pinctrl_get() could be called multiple times for the same device. Rather
> > > than create a whole new struct pinctrl each time it's called, we just
> > > reference count the object so that each call returns the same one, and
> > > it won't be destroyed until all users have called pinctrl_put().
> ...
> > I still can't find in which case the device will have such requirement
> > since per my understanding pinctrl is a little different from clock
> > (clock can be used by different devices but we do not allow pins to be
> > used by difference devices at the same time).
>
> True. It's actually very easy to make pinctrl_get() fail if a struct
> pinctrl was already created for the device in question. If we do that,
> we can completely remove the usecount field. I'll update my patch to do
> that.
Great.
>
> > > > > +static inline struct pinctrl * __must_check pinctrl_get_select(
> > > > > + struct device *dev, const char *name)
> > > > > +{
> > > > > + struct pinctrl *p;
> > > > > + struct pinctrl_state *s;
> > > > > + int ret;
> > > > > +
> > > > > + p = pinctrl_get(dev);
> > > > > + if (IS_ERR(p))
> > > > > + return p;
> > > > > +
> > > > > + s = pinctrl_lookup_state(p, name);
> > > > > + if (IS_ERR(s)) {
> > > > > + pinctrl_put(p);
> > > > > + return ERR_PTR(PTR_ERR(s));
> > > > > + }
> > > > > +
> > > > > + ret = pinctrl_select_state(p, s);
> > > > > + if (ret < 0) {
> > > > > + pinctrl_put(p);
> > > > > + return ERR_PTR(ret);
> > > >
> > > > s/ERR_PTR(ret)/ret ?
> > >
> > > The function returns a pointer, whereas ret is an int. ERR_PTR() is used
> > > to wrap the int error code into a pointer value so that the function can
> > > return either a valid pointer, or an error-code. See include/linux/err.h.
> >
> > Hmm, below is what i see in your patch:
> > +int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state)
> > {
> > + int ret;
> > +
> > mutex_lock(&pinctrl_mutex);
> > - pinctrl_disable_locked(p);
> > + ret = pinctrl_select_state_locked(p, state);
> > mutex_unlock(&pinctrl_mutex);
> > +
> > + return ret;
> > }
> >
> > It seems pinctrl_select_state does not return a pointer.
>
> pinctrl_select()_state() returns an int error code.
>
> pinctrl_get_select() returns a pointer, or an error code encoded into a
> pointer.
>
> ERR_PTR(ret) is used to convert pinctrl_select()'s int error code into
> a pointer representation of the error code for pinctrl_get_select() to
> return.
>
Oh, i see.
You're right, sorry for the noise.
Regards
Dong Aisheng