From 546edd83abe4f03472d721c60011c5ff95e25474 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 6 Jan 2012 13:38:31 -0700 Subject: [PATCH 1/7] pinctrl: fix pinconf_pins_show iteration Commit 706e852 "pinctrl: correct a offset while enumerating pins" modified the variable used by pinconf_pin_show()'s for loop, but didn't update the for loop test expression. Signed-off-by: Stephen Warren Signed-off-by: Linus Walleij --- drivers/pinctrl/pinconf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c index 1259872b0a1d..1892a3794b99 100644 --- a/drivers/pinctrl/pinconf.c +++ b/drivers/pinctrl/pinconf.c @@ -236,7 +236,7 @@ static int pinconf_pins_show(struct seq_file *s, void *what) seq_puts(s, "Format: pin (name): pinmux setting array\n"); /* The pin number can be retrived from the pin controller descriptor */ - for (i = 0; pin < pctldev->desc->npins; i++) { + for (i = 0; i < pctldev->desc->npins; i++) { struct pin_desc *desc; pin = pctldev->desc->pins[i].number; From f54367f9de1b52000c008d3f68512f44cc392816 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 19 Jan 2012 22:35:05 +0100 Subject: [PATCH 2/7] Documentation/pinctrl: fix a few syntax errors in code examples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Acked-by: Stephen Warren Signed-off-by: Uwe Kleine-König Signed-off-by: Linus Walleij --- Documentation/pinctrl.txt | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt index 6727b92bc2fb..5324d3199f34 100644 --- a/Documentation/pinctrl.txt +++ b/Documentation/pinctrl.txt @@ -857,42 +857,41 @@ case), we define a mapping like this: ... { - .name "2bit" + .name = "2bit" .ctrl_dev_name = "pinctrl-foo", .function = "mmc0", .group = "mmc0_1_grp", .dev_name = "foo-mmc.0", }, { - .name "4bit" + .name = "4bit" .ctrl_dev_name = "pinctrl-foo", .function = "mmc0", .group = "mmc0_1_grp", .dev_name = "foo-mmc.0", }, { - .name "4bit" + .name = "4bit" .ctrl_dev_name = "pinctrl-foo", .function = "mmc0", .group = "mmc0_2_grp", .dev_name = "foo-mmc.0", }, { - .name "8bit" + .name = "8bit" .ctrl_dev_name = "pinctrl-foo", - .function = "mmc0", .group = "mmc0_1_grp", .dev_name = "foo-mmc.0", }, { - .name "8bit" + .name = "8bit" .ctrl_dev_name = "pinctrl-foo", .function = "mmc0", .group = "mmc0_2_grp", .dev_name = "foo-mmc.0", }, { - .name "8bit" + .name = "8bit" .ctrl_dev_name = "pinctrl-foo", .function = "mmc0", .group = "mmc0_3_grp", @@ -995,7 +994,7 @@ This is enabled by simply setting the .hog_on_boot field in the map to true, like this: { - .name "POWERMAP" + .name = "POWERMAP" .ctrl_dev_name = "pinctrl-foo", .function = "power_func", .hog_on_boot = true, From f9d41d7cb5a3a4fe9585d47e518d779d2aef8c94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 19 Jan 2012 22:42:48 +0100 Subject: [PATCH 3/7] pinctrl: unbreak error messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's better to not line break error messages to allow easier grepping for them even when the line gets >80 chars. Additionally some minor reformating is done. Signed-off-by: Uwe Kleine-König Signed-off-by: Linus Walleij --- drivers/pinctrl/pinmux.c | 46 +++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index a76a348321bb..0b22037965b9 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c @@ -152,8 +152,7 @@ static int pin_request(struct pinctrl_dev *pctldev, status = 0; if (status) - dev_err(pctldev->dev, "->request on device %s failed " - "for pin %d\n", + dev_err(pctldev->dev, "->request on device %s failed for pin %d\n", pctldev->desc->name, pin); out_free_pin: if (status) { @@ -355,21 +354,20 @@ int __init pinmux_register_mappings(struct pinmux_map const *maps, /* First sanity check the new mapping */ for (i = 0; i < num_maps; i++) { if (!maps[i].name) { - pr_err("failed to register map %d: " - "no map name given\n", i); + pr_err("failed to register map %d: no map name given\n", + i); return -EINVAL; } if (!maps[i].ctrl_dev && !maps[i].ctrl_dev_name) { - pr_err("failed to register map %s (%d): " - "no pin control device given\n", + 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); + pr_err("failed to register map %s (%d): no function ID given\n", + maps[i].name, i); return -EINVAL; } @@ -442,8 +440,7 @@ static int acquire_pins(struct pinctrl_dev *pctldev, ret = pin_request(pctldev, pins[i], func, NULL); if (ret) { dev_err(pctldev->dev, - "could not get pin %d for function %s " - "on device %s - conflicting mux mappings?\n", + "could not get pin %d for function %s on device %s - conflicting mux mappings?\n", pins[i], func ? : "(undefined)", pinctrl_dev_get_name(pctldev)); /* On error release all taken pins */ @@ -473,8 +470,7 @@ static void release_pins(struct pinctrl_dev *pctldev, ret = pctlops->get_group_pins(pctldev, group_selector, &pins, &num_pins); if (ret) { - dev_err(pctldev->dev, "could not get pins to release for " - "group selector %d\n", + dev_err(pctldev->dev, "could not get pins to release for group selector %d\n", group_selector); return; } @@ -526,8 +522,7 @@ static int pinmux_check_pin_group(struct pinctrl_dev *pctldev, 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", + "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; @@ -535,8 +530,7 @@ static int pinmux_check_pin_group(struct pinctrl_dev *pctldev, if (num_groups > 1) dev_dbg(pctldev->dev, - "function %s support more than one group, " - "default-selecting first group %s (%d)\n", + "function %s support more than one group, default-selecting first group %s (%d)\n", pmxops->get_function_name(pctldev, func_selector), groups[0], ret); @@ -628,10 +622,8 @@ static int pinmux_enable_muxmap(struct pinctrl_dev *pctldev, if (pmx->pctldev && pmx->pctldev != pctldev) { dev_err(pctldev->dev, - "different pin control devices given for device %s, " - "function %s\n", - devname, - map->function); + "different pin control devices given for device %s, function %s\n", + devname, map->function); return -EINVAL; } pmx->dev = dev; @@ -695,7 +687,6 @@ static void pinmux_free_groups(struct pinmux *pmx) */ struct pinmux *pinmux_get(struct device *dev, const char *name) { - struct pinmux_map const *map = NULL; struct pinctrl_dev *pctldev = NULL; const char *devname = NULL; @@ -745,8 +736,7 @@ struct pinmux *pinmux_get(struct device *dev, const char *name) else if (map->ctrl_dev_name) devname = map->ctrl_dev_name; - pr_warning("could not find a pinctrl device for pinmux " - "function %s, fishy, they shall all have one\n", + 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", devname ? devname : "UNDEFINED"); @@ -932,8 +922,8 @@ static int pinmux_hog_map(struct pinctrl_dev *pctldev, * without any problems, so then we can hog pinmuxes for * all devices that just want a static pin mux at this point. */ - dev_err(pctldev->dev, "map %s wants to hog a non-system " - "pinmux, this is not going to work\n", map->name); + dev_err(pctldev->dev, "map %s wants to hog a non-system pinmux, this is not going to work\n", + map->name); return -EINVAL; } @@ -1122,13 +1112,15 @@ static int pinmux_show(struct seq_file *s, void *what) seq_printf(s, "device: %s function: %s (%u),", pinctrl_dev_get_name(pmx->pctldev), - pmxops->get_function_name(pctldev, pmx->func_selector), + pmxops->get_function_name(pctldev, + pmx->func_selector), pmx->func_selector); seq_printf(s, " groups: ["); list_for_each_entry(grp, &pmx->groups, node) { seq_printf(s, " %s (%u)", - pctlops->get_group_name(pctldev, grp->group_selector), + pctlops->get_group_name(pctldev, + grp->group_selector), grp->group_selector); } seq_printf(s, " ]"); From 0215716083cac67ff7ea3e3efdc9943bdb462274 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Fri, 20 Jan 2012 08:17:22 -0800 Subject: [PATCH 4/7] pinctrl: free debugfs entries when unloading a pinmux driver We were not cleaning up properly after unloading a pinmux driver compiled as module. Signed-off-by: Tony Lindgren Signed-off-by: Linus Walleij --- drivers/pinctrl/core.c | 14 +++++++++++++- drivers/pinctrl/core.h | 3 +++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index 569bdb3ef104..d9d35fcbfc6b 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -510,10 +510,12 @@ static struct dentry *debugfs_root; static void pinctrl_init_device_debugfs(struct pinctrl_dev *pctldev) { - static struct dentry *device_root; + struct dentry *device_root; device_root = debugfs_create_dir(dev_name(pctldev->dev), debugfs_root); + pctldev->device_root = device_root; + if (IS_ERR(device_root) || !device_root) { pr_warn("failed to create debugfs directory for %s\n", dev_name(pctldev->dev)); @@ -529,6 +531,11 @@ static void pinctrl_init_device_debugfs(struct pinctrl_dev *pctldev) pinconf_init_device_debugfs(device_root, pctldev); } +static void pinctrl_remove_device_debugfs(struct pinctrl_dev *pctldev) +{ + debugfs_remove_recursive(pctldev->device_root); +} + static void pinctrl_init_debugfs(void) { debugfs_root = debugfs_create_dir("pinctrl", NULL); @@ -553,6 +560,10 @@ static void pinctrl_init_debugfs(void) { } +static void pinctrl_remove_device_debugfs(struct pinctrl_dev *pctldev) +{ +} + #endif /** @@ -641,6 +652,7 @@ void pinctrl_unregister(struct pinctrl_dev *pctldev) if (pctldev == NULL) return; + pinctrl_remove_device_debugfs(pctldev); pinmux_unhog_maps(pctldev); /* TODO: check that no pinmuxes are still active? */ mutex_lock(&pinctrldev_list_mutex); diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h index 177a3310547f..cfa86da6b4b1 100644 --- a/drivers/pinctrl/core.h +++ b/drivers/pinctrl/core.h @@ -41,6 +41,9 @@ struct pinctrl_dev { struct device *dev; struct module *owner; void *driver_data; +#ifdef CONFIG_DEBUG_FS + struct dentry *device_root; +#endif #ifdef CONFIG_PINMUX struct mutex pinmux_hogs_lock; struct list_head pinmux_hogs; From de849eecd0addaa6bf60f2f7be36b30abf9ff2ae Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Fri, 20 Jan 2012 08:17:33 -0800 Subject: [PATCH 5/7] pinctrl: fix some pinmux typos Fix some pinmux typos so implementing pinmux drivers is a bit easier. Signed-off-by: Tony Lindgren Signed-off-by: Linus Walleij --- Documentation/pinctrl.txt | 2 +- drivers/pinctrl/pinmux.c | 9 ++------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt index 5324d3199f34..150fd3833d0b 100644 --- a/Documentation/pinctrl.txt +++ b/Documentation/pinctrl.txt @@ -1024,7 +1024,7 @@ it, disables and releases it, and muxes it in on the pins defined by group B: foo_switch() { - struct pinmux pmx; + struct pinmux *pmx; /* Enable on position A */ pmx = pinmux_get(&device, "spi0-pos-A"); diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index 0b22037965b9..f4f8c7e4b1c8 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c @@ -53,11 +53,6 @@ struct pinmux_group { * @dev: the device using this pinmux * @usecount: the number of active users of this mux setting, used to keep * track of nested use cases - * @pins: an array of discrete physical pins used in this mapping, taken - * from the global pin enumeration space (copied from pinmux map) - * @num_pins: the number of pins in this mapping array, i.e. the number of - * elements in .pins so we can iterate over that array (copied from - * pinmux map) * @pctldev: pin control device handling this pinmux * @func_selector: the function selector for the pinmux device handling * this pinmux @@ -409,7 +404,7 @@ int __init pinmux_register_mappings(struct pinmux_map const *maps, } /** - * acquire_pins() - acquire all the pins for a certain funcion on a pinmux + * 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 * @group_selector: the group selector containing the pins to acquire @@ -455,7 +450,7 @@ static int acquire_pins(struct pinctrl_dev *pctldev, /** * release_pins() - release pins taken by earlier acquirement - * @pctldev: the device to free the pinx on + * @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, From 9e2551e10b5c7ba550849bd9ed519e498cc30e68 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Fri, 20 Jan 2012 07:43:53 -0800 Subject: [PATCH 6/7] pinctrl: fix pinmux_hog_maps when ctrl_dev_name is not set The ctrl_dev_name is optional for struct pinmux_map assuming that ctrl_dev is set. Without this patch we can get: Unable to handle kernel NULL pointer dereference at virtual address 00000000 ... (pinmux_hog_maps+0xa4/0x20c) (pinctrl_register+0x2a4/0x378) ... Fix this by adding adding a test for map->ctrl_dev. Additionally move the test for map->ctrl_dev earlier to optimize out the loop a bit. Signed-off-by: Tony Lindgren Acked-by: Stephen Warren Signed-off-by: Linus Walleij --- drivers/pinctrl/pinmux.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index f4f8c7e4b1c8..3ffa9324ed82 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c @@ -978,9 +978,12 @@ int pinmux_hog_maps(struct pinctrl_dev *pctldev) for (i = 0; i < pinmux_maps_num; i++) { struct pinmux_map const *map = &pinmux_maps[i]; - if (((map->ctrl_dev == dev) || - !strcmp(map->ctrl_dev_name, devname)) && - map->hog_on_boot) { + if (!map->hog_on_boot) + continue; + + if ((map->ctrl_dev == dev) || + (map->ctrl_dev_name && + !strcmp(map->ctrl_dev_name, devname))) { /* OK time to hog! */ ret = pinmux_hog_map(pctldev, map); if (ret) From b9130b776ee481acbc27a7e56d98df75680de369 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 24 Jan 2012 16:28:08 -0800 Subject: [PATCH 7/7] pinctrl: add checks for empty function names This is needed as otherwise we can get the following when dealing with buggy data in a pinmux driver for pinmux_search_function: Unable to handle kernel NULL pointer dereference at virtual address 00000000 ... PC is at strcmp+0xc/0x34 LR is at pinmux_get+0x350/0x8f4 ... As we need pctldev initialized to call ops->list_functions, let's initialize it before check_ops calls and pass the pctldev to the check_ops functions. Do this for both pinmux and pinconf check_ops functions. Signed-off-by: Tony Lindgren Signed-off-by: Linus Walleij --- drivers/pinctrl/core.c | 40 +++++++++++++++++++-------------------- drivers/pinctrl/pinconf.c | 4 +++- drivers/pinctrl/pinconf.h | 4 ++-- drivers/pinctrl/pinmux.c | 17 ++++++++++++++++- drivers/pinctrl/pinmux.h | 4 ++-- 5 files changed, 43 insertions(+), 26 deletions(-) diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index d9d35fcbfc6b..8fe15cf15ac8 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -583,26 +583,6 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc, if (pctldesc->name == NULL) return NULL; - /* If we're implementing pinmuxing, check the ops for sanity */ - if (pctldesc->pmxops) { - ret = pinmux_check_ops(pctldesc->pmxops); - if (ret) { - pr_err("%s pinmux ops lacks necessary functions\n", - pctldesc->name); - return NULL; - } - } - - /* If we're implementing pinconfig, check the ops for sanity */ - if (pctldesc->confops) { - ret = pinconf_check_ops(pctldesc->confops); - if (ret) { - pr_err("%s pin config ops lacks necessary functions\n", - pctldesc->name); - return NULL; - } - } - pctldev = kzalloc(sizeof(struct pinctrl_dev), GFP_KERNEL); if (pctldev == NULL) return NULL; @@ -617,6 +597,26 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc, mutex_init(&pctldev->gpio_ranges_lock); pctldev->dev = dev; + /* If we're implementing pinmuxing, check the ops for sanity */ + if (pctldesc->pmxops) { + ret = pinmux_check_ops(pctldev); + if (ret) { + pr_err("%s pinmux ops lacks necessary functions\n", + pctldesc->name); + goto out_err; + } + } + + /* If we're implementing pinconfig, check the ops for sanity */ + if (pctldesc->confops) { + ret = pinconf_check_ops(pctldev); + if (ret) { + pr_err("%s pin config ops lacks necessary functions\n", + pctldesc->name); + goto out_err; + } + } + /* Register all the pins */ pr_debug("try to register %d pins on %s...\n", pctldesc->npins, pctldesc->name); diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c index 1892a3794b99..9fb75456824c 100644 --- a/drivers/pinctrl/pinconf.c +++ b/drivers/pinctrl/pinconf.c @@ -205,8 +205,10 @@ int pin_config_group_set(const char *dev_name, const char *pin_group, } EXPORT_SYMBOL(pin_config_group_set); -int pinconf_check_ops(const struct pinconf_ops *ops) +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; diff --git a/drivers/pinctrl/pinconf.h b/drivers/pinctrl/pinconf.h index e7dc6165032a..006b77fa737e 100644 --- a/drivers/pinctrl/pinconf.h +++ b/drivers/pinctrl/pinconf.h @@ -13,7 +13,7 @@ #ifdef CONFIG_PINCONF -int pinconf_check_ops(const struct pinconf_ops *ops); +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, @@ -23,7 +23,7 @@ int pin_config_set_for_pin(struct pinctrl_dev *pctldev, unsigned pin, #else -static inline int pinconf_check_ops(const struct pinconf_ops *ops) +static inline int pinconf_check_ops(struct pinctrl_dev *pctldev) { return 0; } diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index 3ffa9324ed82..7c3193f7a044 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c @@ -889,8 +889,11 @@ void pinmux_disable(struct pinmux *pmx) } EXPORT_SYMBOL_GPL(pinmux_disable); -int pinmux_check_ops(const struct pinmux_ops *ops) +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 || @@ -899,6 +902,18 @@ int pinmux_check_ops(const struct pinmux_ops *ops) !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; } diff --git a/drivers/pinctrl/pinmux.h b/drivers/pinctrl/pinmux.h index 844500b3331b..97f52223fbc2 100644 --- a/drivers/pinctrl/pinmux.h +++ b/drivers/pinctrl/pinmux.h @@ -12,7 +12,7 @@ */ #ifdef CONFIG_PINMUX -int pinmux_check_ops(const struct pinmux_ops *ops); +int pinmux_check_ops(struct pinctrl_dev *pctldev); void pinmux_init_device_debugfs(struct dentry *devroot, struct pinctrl_dev *pctldev); void pinmux_init_debugfs(struct dentry *subsys_root); @@ -21,7 +21,7 @@ void pinmux_unhog_maps(struct pinctrl_dev *pctldev); #else -static inline int pinmux_check_ops(const struct pinmux_ops *ops) +static inline int pinmux_check_ops(struct pinctrl_dev *pctldev) { return 0; }