summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-01-10 10:19:57 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2012-01-10 10:19:57 -0800
commitd52739c62e0096dccea59f012d80256c6e359a98 (patch)
tree4df8ae0640c360eb79b6d0511f084b2337e21e12 /drivers
parentabce00f962a11ed6f748c2569e11695a30716b53 (diff)
parent0d2006bbf09e817f125ba1e42b2549bc2c5d7351 (diff)
downloadblackbird-op-linux-d52739c62e0096dccea59f012d80256c6e359a98.tar.gz
blackbird-op-linux-d52739c62e0096dccea59f012d80256c6e359a98.zip
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl
* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (31 commits) pinctrl: remove unnecessary max pin number pinctrl: correct a offset while enumerating pins pinctrl: some typo fixes pinctrl: rename U300 and SIRF pin controllers pinctrl: pass name instead of device to pin_config_* pinctrl: add "struct seq_file;" to pinconf.h pinctrl: conjure names for unnamed pins pinctrl: add a group-specific hog macro pinctrl: don't create a device for each pin controller arm/u300: don't use PINMUX_MAP_PRIMARY* pinctrl: implement PINMUX_MAP_SYS_HOG pinctrl: add a pin config interface pinctrl/coh901: driver to request its pins pinctrl: u300-pinmux: register proper GPIO ranges pinctrl: move the U300 GPIO driver to pinctrl ARM: u300: localize GPIO assignments pinctrl: make it possible to add multiple maps pinctrl: make a copy of pinmux map pinctrl: GPIO direction support for muxing pinctrl: print pin range in GPIO range debugs ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpio/Kconfig9
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/pinctrl/Kconfig22
-rw-r--r--drivers/pinctrl/Makefile8
-rw-r--r--drivers/pinctrl/core.c143
-rw-r--r--drivers/pinctrl/core.h13
-rw-r--r--drivers/pinctrl/pinconf.c326
-rw-r--r--drivers/pinctrl/pinconf.h36
-rw-r--r--drivers/pinctrl/pinctrl-coh901.c (renamed from drivers/gpio/gpio-u300.c)21
-rw-r--r--drivers/pinctrl/pinctrl-sirf.c (renamed from drivers/pinctrl/pinmux-sirf.c)9
-rw-r--r--drivers/pinctrl/pinctrl-u300.c (renamed from drivers/pinctrl/pinmux-u300.c)47
-rw-r--r--drivers/pinctrl/pinmux.c265
12 files changed, 722 insertions, 178 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index e3380137b05b..573532f7553e 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -176,15 +176,6 @@ config GPIO_SCH
The Intel Tunnel Creek processor has 5 GPIOs powered by the
core power rail and 9 from suspend power supply.
-config GPIO_U300
- bool "ST-Ericsson U300 COH 901 335/571 GPIO"
- depends on GPIOLIB && ARCH_U300
- help
- Say yes here to support GPIO interface on ST-Ericsson U300.
- The names of the two IP block variants supported are
- COH 901 335 and COH 901 571/3. They contain 3, 5 or 7
- ports of 8 GPIO pins each.
-
config GPIO_VX855
tristate "VIA VX855/VX875 GPIO"
depends on PCI
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 8ef9e9abe970..62e641e79e8f 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -54,7 +54,6 @@ obj-$(CONFIG_ARCH_DAVINCI_TNETV107X) += gpio-tnetv107x.o
obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o
obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o
obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o
-obj-$(CONFIG_MACH_U300) += gpio-u300.o
obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o
obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o
obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index e17e2f8001d2..afaf88558125 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -12,7 +12,10 @@ menu "Pin controllers"
depends on PINCTRL
config PINMUX
- bool "Support pinmux controllers"
+ bool "Support pin multiplexing controllers"
+
+config PINCONF
+ bool "Support pin configuration controllers"
config DEBUG_PINCTRL
bool "Debug PINCTRL calls"
@@ -20,16 +23,25 @@ config DEBUG_PINCTRL
help
Say Y here to add some extra checks and diagnostics to PINCTRL calls.
-config PINMUX_SIRF
- bool "CSR SiRFprimaII pinmux driver"
+config PINCTRL_SIRF
+ bool "CSR SiRFprimaII pin controller driver"
depends on ARCH_PRIMA2
select PINMUX
-config PINMUX_U300
- bool "U300 pinmux driver"
+config PINCTRL_U300
+ bool "U300 pin controller driver"
depends on ARCH_U300
select PINMUX
+config PINCTRL_COH901
+ bool "ST-Ericsson U300 COH 901 335/571 GPIO"
+ depends on GPIOLIB && ARCH_U300 && PINMUX_U300
+ help
+ Say yes here to support GPIO interface on ST-Ericsson U300.
+ The names of the two IP block variants supported are
+ COH 901 335 and COH 901 571/3. They contain 3, 5 or 7
+ ports of 8 GPIO pins each.
+
endmenu
endif
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index bdc548a6b7e9..827601cc68f6 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -1,8 +1,10 @@
# generic pinmux support
-ccflags-$(CONFIG_DEBUG_PINMUX) += -DDEBUG
+ccflags-$(CONFIG_DEBUG_PINCTRL) += -DDEBUG
obj-$(CONFIG_PINCTRL) += core.o
obj-$(CONFIG_PINMUX) += pinmux.o
-obj-$(CONFIG_PINMUX_SIRF) += pinmux-sirf.o
-obj-$(CONFIG_PINMUX_U300) += pinmux-u300.o
+obj-$(CONFIG_PINCONF) += pinconf.o
+obj-$(CONFIG_PINCTRL_SIRF) += pinctrl-sirf.o
+obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o
+obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index eadef9e191ea..569bdb3ef104 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -28,17 +28,12 @@
#include <linux/pinctrl/machine.h>
#include "core.h"
#include "pinmux.h"
+#include "pinconf.h"
/* Global list of pin control devices */
static DEFINE_MUTEX(pinctrldev_list_mutex);
static LIST_HEAD(pinctrldev_list);
-static void pinctrl_dev_release(struct device *dev)
-{
- struct pinctrl_dev *pctldev = dev_get_drvdata(dev);
- kfree(pctldev);
-}
-
const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev)
{
/* We're not allowed to register devices without name */
@@ -70,14 +65,14 @@ struct pinctrl_dev *get_pinctrl_dev_from_dev(struct device *dev,
mutex_lock(&pinctrldev_list_mutex);
list_for_each_entry(pctldev, &pinctrldev_list, node) {
- if (dev && &pctldev->dev == dev) {
+ if (dev && pctldev->dev == dev) {
/* Matched on device pointer */
found = true;
break;
}
if (devname &&
- !strcmp(dev_name(&pctldev->dev), devname)) {
+ !strcmp(dev_name(pctldev->dev), devname)) {
/* Matched on device name */
found = true;
break;
@@ -88,7 +83,7 @@ struct pinctrl_dev *get_pinctrl_dev_from_dev(struct device *dev,
return found ? pctldev : NULL;
}
-struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, int pin)
+struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, unsigned int pin)
{
struct pin_desc *pindesc;
unsigned long flags;
@@ -101,6 +96,31 @@ struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, int pin)
}
/**
+ * pin_get_from_name() - look up a pin number from a name
+ * @pctldev: the pin control device to lookup the pin on
+ * @name: the name of the pin to look up
+ */
+int pin_get_from_name(struct pinctrl_dev *pctldev, const char *name)
+{
+ unsigned i, pin;
+
+ /* The pin number can be retrived from the pin controller descriptor */
+ for (i = 0; i < pctldev->desc->npins; i++) {
+ struct pin_desc *desc;
+
+ pin = pctldev->desc->pins[i].number;
+ desc = pin_desc_get(pctldev, pin);
+ /* Pin space may be sparse */
+ if (desc == NULL)
+ continue;
+ if (desc->name && !strcmp(name, desc->name))
+ return pin;
+ }
+
+ return -EINVAL;
+}
+
+/**
* pin_is_valid() - check if pin exists on controller
* @pctldev: the pin control device to check the pin on
* @pin: pin to check, use the local pin controller index number
@@ -139,6 +159,8 @@ static void pinctrl_free_pindescs(struct pinctrl_dev *pctldev,
if (pindesc != NULL) {
radix_tree_delete(&pctldev->pin_desc_tree,
pins[i].number);
+ if (pindesc->dynamic_name)
+ kfree(pindesc->name);
}
kfree(pindesc);
}
@@ -160,19 +182,27 @@ static int pinctrl_register_one_pin(struct pinctrl_dev *pctldev,
pindesc = kzalloc(sizeof(*pindesc), GFP_KERNEL);
if (pindesc == NULL)
return -ENOMEM;
+
spin_lock_init(&pindesc->lock);
/* Set owner */
pindesc->pctldev = pctldev;
/* Copy basic pin info */
- pindesc->name = name;
+ if (pindesc->name) {
+ pindesc->name = name;
+ } else {
+ pindesc->name = kasprintf(GFP_KERNEL, "PIN%u", number);
+ if (pindesc->name == NULL)
+ return -ENOMEM;
+ pindesc->dynamic_name = true;
+ }
spin_lock(&pctldev->pin_desc_tree_lock);
radix_tree_insert(&pctldev->pin_desc_tree, number, pindesc);
spin_unlock(&pctldev->pin_desc_tree_lock);
pr_debug("registered pin %d (%s) on %s\n",
- number, name ? name : "(unnamed)", pctldev->desc->name);
+ number, pindesc->name, pctldev->desc->name);
return 0;
}
@@ -284,21 +314,52 @@ void pinctrl_remove_gpio_range(struct pinctrl_dev *pctldev,
mutex_unlock(&pctldev->gpio_ranges_lock);
}
+/**
+ * pinctrl_get_group_selector() - returns the group selector for a group
+ * @pctldev: the pin controller handling the group
+ * @pin_group: the pin group to look up
+ */
+int pinctrl_get_group_selector(struct pinctrl_dev *pctldev,
+ const char *pin_group)
+{
+ const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
+ unsigned group_selector = 0;
+
+ while (pctlops->list_groups(pctldev, group_selector) >= 0) {
+ const char *gname = pctlops->get_group_name(pctldev,
+ group_selector);
+ if (!strcmp(gname, pin_group)) {
+ dev_dbg(pctldev->dev,
+ "found group selector %u for %s\n",
+ group_selector,
+ pin_group);
+ return group_selector;
+ }
+
+ group_selector++;
+ }
+
+ dev_err(pctldev->dev, "does not have pin group %s\n",
+ pin_group);
+
+ return -EINVAL;
+}
+
#ifdef CONFIG_DEBUG_FS
static int pinctrl_pins_show(struct seq_file *s, void *what)
{
struct pinctrl_dev *pctldev = s->private;
const struct pinctrl_ops *ops = pctldev->desc->pctlops;
- unsigned pin;
+ unsigned i, pin;
seq_printf(s, "registered pins: %d\n", pctldev->desc->npins);
- seq_printf(s, "max pin number: %d\n", pctldev->desc->maxpin);
- /* The highest pin number need to be included in the loop, thus <= */
- for (pin = 0; pin <= pctldev->desc->maxpin; pin++) {
+ /* The pin number can be retrived from the pin controller descriptor */
+ for (i = 0; i < pctldev->desc->npins; i++) {
struct pin_desc *desc;
+ pin = pctldev->desc->pins[i].number;
desc = pin_desc_get(pctldev, pin);
/* Pin space may be sparse */
if (desc == NULL)
@@ -363,8 +424,11 @@ static int pinctrl_gpioranges_show(struct seq_file *s, void *what)
/* Loop over the ranges */
mutex_lock(&pctldev->gpio_ranges_lock);
list_for_each_entry(range, &pctldev->gpio_ranges, node) {
- seq_printf(s, "%u: %s [%u - %u]\n", range->id, range->name,
- range->base, (range->base + range->npins - 1));
+ seq_printf(s, "%u: %s GPIOS [%u - %u] PINS [%u - %u]\n",
+ range->id, range->name,
+ range->base, (range->base + range->npins - 1),
+ range->pin_base,
+ (range->pin_base + range->npins - 1));
}
mutex_unlock(&pctldev->gpio_ranges_lock);
@@ -375,11 +439,15 @@ static int pinctrl_devices_show(struct seq_file *s, void *what)
{
struct pinctrl_dev *pctldev;
- seq_puts(s, "name [pinmux]\n");
+ seq_puts(s, "name [pinmux] [pinconf]\n");
mutex_lock(&pinctrldev_list_mutex);
list_for_each_entry(pctldev, &pinctrldev_list, node) {
seq_printf(s, "%s ", pctldev->desc->name);
if (pctldev->desc->pmxops)
+ seq_puts(s, "yes ");
+ else
+ seq_puts(s, "no ");
+ if (pctldev->desc->confops)
seq_puts(s, "yes");
else
seq_puts(s, "no");
@@ -444,11 +512,11 @@ static void pinctrl_init_device_debugfs(struct pinctrl_dev *pctldev)
{
static struct dentry *device_root;
- device_root = debugfs_create_dir(dev_name(&pctldev->dev),
+ device_root = debugfs_create_dir(dev_name(pctldev->dev),
debugfs_root);
if (IS_ERR(device_root) || !device_root) {
pr_warn("failed to create debugfs directory for %s\n",
- dev_name(&pctldev->dev));
+ dev_name(pctldev->dev));
return;
}
debugfs_create_file("pins", S_IFREG | S_IRUGO,
@@ -458,6 +526,7 @@ static void pinctrl_init_device_debugfs(struct pinctrl_dev *pctldev)
debugfs_create_file("gpio-ranges", S_IFREG | S_IRUGO,
device_root, pctldev, &pinctrl_gpioranges_ops);
pinmux_init_device_debugfs(device_root, pctldev);
+ pinconf_init_device_debugfs(device_root, pctldev);
}
static void pinctrl_init_debugfs(void)
@@ -495,7 +564,6 @@ static void pinctrl_init_debugfs(void)
struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
struct device *dev, void *driver_data)
{
- static atomic_t pinmux_no = ATOMIC_INIT(0);
struct pinctrl_dev *pctldev;
int ret;
@@ -514,6 +582,16 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
}
}
+ /* If we're implementing pinconfig, check the ops for sanity */
+ if (pctldesc->confops) {
+ ret = pinconf_check_ops(pctldesc->confops);
+ if (ret) {
+ pr_err("%s pin config ops lacks necessary functions\n",
+ pctldesc->name);
+ return NULL;
+ }
+ }
+
pctldev = kzalloc(sizeof(struct pinctrl_dev), GFP_KERNEL);
if (pctldev == NULL)
return NULL;
@@ -526,18 +604,7 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
spin_lock_init(&pctldev->pin_desc_tree_lock);
INIT_LIST_HEAD(&pctldev->gpio_ranges);
mutex_init(&pctldev->gpio_ranges_lock);
-
- /* Register device */
- pctldev->dev.parent = dev;
- dev_set_name(&pctldev->dev, "pinctrl.%d",
- atomic_inc_return(&pinmux_no) - 1);
- pctldev->dev.release = pinctrl_dev_release;
- ret = device_register(&pctldev->dev);
- if (ret != 0) {
- pr_err("error in device registration\n");
- goto out_reg_dev_err;
- }
- dev_set_drvdata(&pctldev->dev, pctldev);
+ pctldev->dev = dev;
/* Register all the pins */
pr_debug("try to register %d pins on %s...\n",
@@ -547,7 +614,7 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
pr_err("error during pin registration\n");
pinctrl_free_pindescs(pctldev, pctldesc->pins,
pctldesc->npins);
- goto out_reg_pins_err;
+ goto out_err;
}
pinctrl_init_device_debugfs(pctldev);
@@ -557,10 +624,8 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
pinmux_hog_maps(pctldev);
return pctldev;
-out_reg_pins_err:
- device_del(&pctldev->dev);
-out_reg_dev_err:
- put_device(&pctldev->dev);
+out_err:
+ kfree(pctldev);
return NULL;
}
EXPORT_SYMBOL_GPL(pinctrl_register);
@@ -584,7 +649,7 @@ void pinctrl_unregister(struct pinctrl_dev *pctldev)
/* Destroy descriptor tree */
pinctrl_free_pindescs(pctldev, pctldev->desc->pins,
pctldev->desc->npins);
- device_unregister(&pctldev->dev);
+ kfree(pctldev);
}
EXPORT_SYMBOL_GPL(pinctrl_unregister);
diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h
index 472fa1341cc0..177a3310547f 100644
--- a/drivers/pinctrl/core.h
+++ b/drivers/pinctrl/core.h
@@ -9,6 +9,10 @@
* License terms: GNU General Public License (GPL) version 2
*/
+#include <linux/pinctrl/pinconf.h>
+
+struct pinctrl_gpio_range;
+
/**
* struct pinctrl_dev - pin control class device
* @node: node to include this pin controller in the global pin controller list
@@ -34,7 +38,7 @@ struct pinctrl_dev {
spinlock_t pin_desc_tree_lock;
struct list_head gpio_ranges;
struct mutex gpio_ranges_lock;
- struct device dev;
+ struct device *dev;
struct module *owner;
void *driver_data;
#ifdef CONFIG_PINMUX
@@ -48,6 +52,7 @@ struct pinctrl_dev {
* @pctldev: corresponding pin control device
* @name: a name for the pin, e.g. the name of the pin/pad/finger on a
* datasheet or such
+ * @dynamic_name: if the name of this pin was dynamically allocated
* @lock: a lock to protect the descriptor structure
* @mux_requested: whether the pin is already requested by pinmux or not
* @mux_function: a named muxing function for the pin that will be passed to
@@ -56,6 +61,7 @@ struct pinctrl_dev {
struct pin_desc {
struct pinctrl_dev *pctldev;
const char *name;
+ bool dynamic_name;
spinlock_t lock;
/* These fields only added when supporting pinmux drivers */
#ifdef CONFIG_PINMUX
@@ -65,7 +71,10 @@ struct pin_desc {
struct pinctrl_dev *get_pinctrl_dev_from_dev(struct device *dev,
const char *dev_name);
-struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, int pin);
+struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, unsigned int pin);
+int 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);
diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c
new file mode 100644
index 000000000000..1259872b0a1d
--- /dev/null
+++ b/drivers/pinctrl/pinconf.c
@@ -0,0 +1,326 @@
+/*
+ * Core driver for the pin config portions of the pin control subsystem
+ *
+ * Copyright (C) 2011 ST-Ericsson SA
+ * Written on behalf of Linaro for ST-Ericsson
+ *
+ * Author: Linus Walleij <linus.walleij@linaro.org>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+#define pr_fmt(fmt) "pinconfig core: " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinconf.h>
+#include "core.h"
+#include "pinconf.h"
+
+int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
+ unsigned long *config)
+{
+ const struct pinconf_ops *ops = pctldev->desc->confops;
+
+ if (!ops || !ops->pin_config_get) {
+ dev_err(pctldev->dev, "cannot get pin configuration, missing "
+ "pin_config_get() function in driver\n");
+ return -EINVAL;
+ }
+
+ return ops->pin_config_get(pctldev, pin, config);
+}
+
+/**
+ * pin_config_get() - get the configuration of a single pin parameter
+ * @dev_name: name of the pin controller device for this pin
+ * @name: name of the pin to get the config for
+ * @config: the config pointed to by this argument will be filled in with the
+ * current pin state, it can be used directly by drivers as a numeral, or
+ * it can be dereferenced to any struct.
+ */
+int pin_config_get(const char *dev_name, const char *name,
+ unsigned long *config)
+{
+ struct pinctrl_dev *pctldev;
+ int pin;
+
+ pctldev = get_pinctrl_dev_from_dev(NULL, dev_name);
+ if (!pctldev)
+ return -EINVAL;
+
+ pin = pin_get_from_name(pctldev, name);
+ if (pin < 0)
+ return pin;
+
+ return pin_config_get_for_pin(pctldev, pin, config);
+}
+EXPORT_SYMBOL(pin_config_get);
+
+int pin_config_set_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
+ unsigned long config)
+{
+ const struct pinconf_ops *ops = pctldev->desc->confops;
+ int ret;
+
+ if (!ops || !ops->pin_config_set) {
+ dev_err(pctldev->dev, "cannot configure pin, missing "
+ "config function in driver\n");
+ return -EINVAL;
+ }
+
+ ret = ops->pin_config_set(pctldev, pin, config);
+ if (ret) {
+ dev_err(pctldev->dev,
+ "unable to set pin configuration on pin %d\n", pin);
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * pin_config_set() - set the configuration of a single pin parameter
+ * @dev_name: name of pin controller device for this pin
+ * @name: name of the pin to set the config for
+ * @config: the config in this argument will contain the desired pin state, it
+ * can be used directly by drivers as a numeral, or it can be dereferenced
+ * to any struct.
+ */
+int pin_config_set(const char *dev_name, const char *name,
+ unsigned long config)
+{
+ struct pinctrl_dev *pctldev;
+ int pin;
+
+ pctldev = get_pinctrl_dev_from_dev(NULL, dev_name);
+ if (!pctldev)
+ return -EINVAL;
+
+ pin = pin_get_from_name(pctldev, name);
+ if (pin < 0)
+ return pin;
+
+ return pin_config_set_for_pin(pctldev, pin, config);
+}
+EXPORT_SYMBOL(pin_config_set);
+
+int pin_config_group_get(const char *dev_name, const char *pin_group,
+ unsigned long *config)
+{
+ struct pinctrl_dev *pctldev;
+ const struct pinconf_ops *ops;
+ int selector;
+
+ pctldev = get_pinctrl_dev_from_dev(NULL, dev_name);
+ if (!pctldev)
+ return -EINVAL;
+ ops = pctldev->desc->confops;
+
+ if (!ops || !ops->pin_config_group_get) {
+ dev_err(pctldev->dev, "cannot get configuration for pin "
+ "group, missing group config get function in "
+ "driver\n");
+ return -EINVAL;
+ }
+
+ selector = pinctrl_get_group_selector(pctldev, pin_group);
+ if (selector < 0)
+ return selector;
+
+ return ops->pin_config_group_get(pctldev, selector, config);
+}
+EXPORT_SYMBOL(pin_config_group_get);
+
+
+int pin_config_group_set(const char *dev_name, const char *pin_group,
+ unsigned long config)
+{
+ struct pinctrl_dev *pctldev;
+ const struct pinconf_ops *ops;
+ const struct pinctrl_ops *pctlops;
+ int selector;
+ const unsigned *pins;
+ unsigned num_pins;
+ int ret;
+ int i;
+
+ pctldev = get_pinctrl_dev_from_dev(NULL, dev_name);
+ if (!pctldev)
+ return -EINVAL;
+ ops = pctldev->desc->confops;
+ pctlops = pctldev->desc->pctlops;
+
+ if (!ops || (!ops->pin_config_group_set && !ops->pin_config_set)) {
+ dev_err(pctldev->dev, "cannot configure pin group, missing "
+ "config function in driver\n");
+ return -EINVAL;
+ }
+
+ selector = pinctrl_get_group_selector(pctldev, pin_group);
+ if (selector < 0)
+ return selector;
+
+ ret = pctlops->get_group_pins(pctldev, selector, &pins, &num_pins);
+ if (ret) {
+ dev_err(pctldev->dev, "cannot configure pin group, error "
+ "getting pins\n");
+ return ret;
+ }
+
+ /*
+ * If the pin controller supports handling entire groups we use that
+ * capability.
+ */
+ if (ops->pin_config_group_set) {
+ ret = ops->pin_config_group_set(pctldev, selector, config);
+ /*
+ * If the pin controller prefer that a certain group be handled
+ * pin-by-pin as well, it returns -EAGAIN.
+ */
+ if (ret != -EAGAIN)
+ return ret;
+ }
+
+ /*
+ * If the controller cannot handle entire groups, we configure each pin
+ * individually.
+ */
+ if (!ops->pin_config_set)
+ return 0;
+
+ for (i = 0; i < num_pins; i++) {
+ ret = ops->pin_config_set(pctldev, pins[i], config);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(pin_config_group_set);
+
+int pinconf_check_ops(const struct pinconf_ops *ops)
+{
+ /* We must be able to read out pin status */
+ if (!ops->pin_config_get && !ops->pin_config_group_get)
+ return -EINVAL;
+ /* We have to be able to config the pins in SOME way */
+ if (!ops->pin_config_set && !ops->pin_config_group_set)
+ return -EINVAL;
+ return 0;
+}
+
+#ifdef CONFIG_DEBUG_FS
+
+static void pinconf_dump_pin(struct pinctrl_dev *pctldev,
+ struct seq_file *s, int pin)
+{
+ const struct pinconf_ops *ops = pctldev->desc->confops;
+
+ if (ops && ops->pin_config_dbg_show)
+ ops->pin_config_dbg_show(pctldev, s, pin);
+}
+
+static int pinconf_pins_show(struct seq_file *s, void *what)
+{
+ struct pinctrl_dev *pctldev = s->private;
+ unsigned i, pin;
+
+ seq_puts(s, "Pin config settings per pin\n");
+ 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++) {
+ struct pin_desc *desc;
+
+ pin = pctldev->desc->pins[i].number;
+ desc = pin_desc_get(pctldev, pin);
+ /* Skip if we cannot search the pin */
+ if (desc == NULL)
+ continue;
+
+ seq_printf(s, "pin %d (%s):", pin,
+ desc->name ? desc->name : "unnamed");
+
+ pinconf_dump_pin(pctldev, s, pin);
+
+ seq_printf(s, "\n");
+ }
+
+ return 0;
+}
+
+static void pinconf_dump_group(struct pinctrl_dev *pctldev,
+ struct seq_file *s, unsigned selector,
+ const char *gname)
+{
+ const struct pinconf_ops *ops = pctldev->desc->confops;
+
+ if (ops && ops->pin_config_group_dbg_show)
+ ops->pin_config_group_dbg_show(pctldev, s, selector);
+}
+
+static int pinconf_groups_show(struct seq_file *s, void *what)
+{
+ struct pinctrl_dev *pctldev = s->private;
+ const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
+ const struct pinconf_ops *ops = pctldev->desc->confops;
+ unsigned selector = 0;
+
+ if (!ops || !ops->pin_config_group_get)
+ return 0;
+
+ seq_puts(s, "Pin config settings per pin group\n");
+ seq_puts(s, "Format: group (name): pinmux setting array\n");
+
+ while (pctlops->list_groups(pctldev, selector) >= 0) {
+ const char *gname = pctlops->get_group_name(pctldev, selector);
+
+ seq_printf(s, "%u (%s):", selector, gname);
+ pinconf_dump_group(pctldev, s, selector, gname);
+ selector++;
+ }
+
+ return 0;
+}
+
+static int pinconf_pins_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, pinconf_pins_show, inode->i_private);
+}
+
+static int pinconf_groups_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, pinconf_groups_show, inode->i_private);
+}
+
+static const struct file_operations pinconf_pins_ops = {
+ .open = pinconf_pins_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static const struct file_operations pinconf_groups_ops = {
+ .open = pinconf_groups_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+void pinconf_init_device_debugfs(struct dentry *devroot,
+ struct pinctrl_dev *pctldev)
+{
+ debugfs_create_file("pinconf-pins", S_IFREG | S_IRUGO,
+ devroot, pctldev, &pinconf_pins_ops);
+ debugfs_create_file("pinconf-groups", S_IFREG | S_IRUGO,
+ devroot, pctldev, &pinconf_groups_ops);
+}
+
+#endif
diff --git a/drivers/pinctrl/pinconf.h b/drivers/pinctrl/pinconf.h
new file mode 100644
index 000000000000..e7dc6165032a
--- /dev/null
+++ b/drivers/pinctrl/pinconf.h
@@ -0,0 +1,36 @@
+/*
+ * Internal interface between the core pin control system and the
+ * pin config portions
+ *
+ * Copyright (C) 2011 ST-Ericsson SA
+ * Written on behalf of Linaro for ST-Ericsson
+ * Based on bits of regulator core, gpio core and clk core
+ *
+ * Author: Linus Walleij <linus.walleij@linaro.org>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifdef CONFIG_PINCONF
+
+int pinconf_check_ops(const struct pinconf_ops *ops);
+void pinconf_init_device_debugfs(struct dentry *devroot,
+ struct pinctrl_dev *pctldev);
+int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
+ unsigned long *config);
+int pin_config_set_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
+ unsigned long config);
+
+#else
+
+static inline int pinconf_check_ops(const struct pinconf_ops *ops)
+{
+ return 0;
+}
+
+static inline void pinconf_init_device_debugfs(struct dentry *devroot,
+ struct pinctrl_dev *pctldev)
+{
+}
+
+#endif
diff --git a/drivers/gpio/gpio-u300.c b/drivers/pinctrl/pinctrl-coh901.c
index 4035778852b0..69fb7072a23e 100644
--- a/drivers/gpio/gpio-u300.c
+++ b/drivers/pinctrl/pinctrl-coh901.c
@@ -22,6 +22,7 @@
#include <linux/gpio.h>
#include <linux/list.h>
#include <linux/slab.h>
+#include <linux/pinctrl/pinmux.h>
#include <mach/gpio-u300.h>
/*
@@ -351,6 +352,24 @@ static inline struct u300_gpio *to_u300_gpio(struct gpio_chip *chip)
return container_of(chip, struct u300_gpio, chip);
}
+static int u300_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+ /*
+ * Map back to global GPIO space and request muxing, the direction
+ * parameter does not matter for this controller.
+ */
+ int gpio = chip->base + offset;
+
+ return pinmux_request_gpio(gpio);
+}
+
+static void u300_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+ int gpio = chip->base + offset;
+
+ pinmux_free_gpio(gpio);
+}
+
static int u300_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct u300_gpio *gpio = to_u300_gpio(chip);
@@ -483,6 +502,8 @@ static int u300_gpio_config(struct gpio_chip *chip, unsigned offset,
static struct gpio_chip u300_gpio_chip = {
.label = "u300-gpio-chip",
.owner = THIS_MODULE,
+ .request = u300_gpio_request,
+ .free = u300_gpio_free,
.get = u300_gpio_get,
.set = u300_gpio_set,
.direction_input = u300_gpio_direction_input,
diff --git a/drivers/pinctrl/pinmux-sirf.c b/drivers/pinctrl/pinctrl-sirf.c
index d76cae620956..6b3534cc051a 100644
--- a/drivers/pinctrl/pinmux-sirf.c
+++ b/drivers/pinctrl/pinctrl-sirf.c
@@ -463,7 +463,7 @@ static const struct sirfsoc_padmux spi1_padmux = {
.funcval = BIT(8),
};
-static const unsigned spi1_pins[] = { 33, 34, 35, 36 };
+static const unsigned spi1_pins[] = { 43, 44, 45, 46 };
static const struct sirfsoc_muxmask sdmmc1_muxmask[] = {
{
@@ -1067,7 +1067,7 @@ static int sirfsoc_pinmux_request_gpio(struct pinctrl_dev *pmxdev,
spmx = pinctrl_dev_get_drvdata(pmxdev);
muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group));
- muxval = muxval | (1 << offset);
+ muxval = muxval | (1 << (offset - range->pin_base));
writel(muxval, spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group));
return 0;
@@ -1086,7 +1086,6 @@ static struct pinctrl_desc sirfsoc_pinmux_desc = {
.name = DRIVER_NAME,
.pins = sirfsoc_pads,
.npins = ARRAY_SIZE(sirfsoc_pads),
- .maxpin = SIRFSOC_NUM_PADS - 1,
.pctlops = &sirfsoc_pctrl_ops,
.pmxops = &sirfsoc_pinmux_ops,
.owner = THIS_MODULE,
@@ -1100,21 +1099,25 @@ static struct pinctrl_gpio_range sirfsoc_gpio_ranges[] = {
.name = "sirfsoc-gpio*",
.id = 0,
.base = 0,
+ .pin_base = 0,
.npins = 32,
}, {
.name = "sirfsoc-gpio*",
.id = 1,
.base = 32,
+ .pin_base = 32,
.npins = 32,
}, {
.name = "sirfsoc-gpio*",
.id = 2,
.base = 64,
+ .pin_base = 64,
.npins = 32,
}, {
.name = "sirfsoc-gpio*",
.id = 3,
.base = 96,
+ .pin_base = 96,
.npins = 19,
},
};
diff --git a/drivers/pinctrl/pinmux-u300.c b/drivers/pinctrl/pinctrl-u300.c
index 4858a64131f8..c8d02f1c2b5e 100644
--- a/drivers/pinctrl/pinmux-u300.c
+++ b/drivers/pinctrl/pinctrl-u300.c
@@ -940,20 +940,23 @@ static void u300_pmx_endisable(struct u300_pmx *upmx, unsigned selector,
{
u16 regval, val, mask;
int i;
+ const struct u300_pmx_mask *upmx_mask;
+ upmx_mask = u300_pmx_functions[selector].mask;
for (i = 0; i < ARRAY_SIZE(u300_pmx_registers); i++) {
if (enable)
- val = u300_pmx_functions[selector].mask->bits;
+ val = upmx_mask->bits;
else
val = 0;
- mask = u300_pmx_functions[selector].mask->mask;
+ mask = upmx_mask->mask;
if (mask != 0) {
regval = readw(upmx->virtbase + u300_pmx_registers[i]);
regval &= ~mask;
regval |= val;
writew(regval, upmx->virtbase + u300_pmx_registers[i]);
}
+ upmx_mask++;
}
}
@@ -1016,21 +1019,35 @@ static struct pinmux_ops u300_pmx_ops = {
};
/*
- * FIXME: this will be set to sane values as this driver engulfs
- * drivers/gpio/gpio-u300.c and we really know this stuff.
+ * GPIO ranges handled by the application-side COH901XXX GPIO controller
+ * Very many pins can be converted into GPIO pins, but we only list those
+ * that are useful in practice to cut down on tables.
*/
-static struct pinctrl_gpio_range u300_gpio_range = {
- .name = "COH901*",
- .id = 0,
- .base = 0,
- .npins = 64,
+#define U300_GPIO_RANGE(a, b, c) { .name = "COH901XXX", .id = a, .base= a, \
+ .pin_base = b, .npins = c }
+
+static struct pinctrl_gpio_range u300_gpio_ranges[] = {
+ U300_GPIO_RANGE(10, 426, 1),
+ U300_GPIO_RANGE(11, 180, 1),
+ U300_GPIO_RANGE(12, 165, 1), /* MS/MMC card insertion */
+ U300_GPIO_RANGE(13, 179, 1),
+ U300_GPIO_RANGE(14, 178, 1),
+ U300_GPIO_RANGE(16, 194, 1),
+ U300_GPIO_RANGE(17, 193, 1),
+ U300_GPIO_RANGE(18, 192, 1),
+ U300_GPIO_RANGE(19, 191, 1),
+ U300_GPIO_RANGE(20, 186, 1),
+ U300_GPIO_RANGE(21, 185, 1),
+ U300_GPIO_RANGE(22, 184, 1),
+ U300_GPIO_RANGE(23, 183, 1),
+ U300_GPIO_RANGE(24, 182, 1),
+ U300_GPIO_RANGE(25, 181, 1),
};
static struct pinctrl_desc u300_pmx_desc = {
.name = DRIVER_NAME,
.pins = u300_pads,
.npins = ARRAY_SIZE(u300_pads),
- .maxpin = U300_NUM_PADS-1,
.pctlops = &u300_pctrl_ops,
.pmxops = &u300_pmx_ops,
.owner = THIS_MODULE,
@@ -1038,9 +1055,10 @@ static struct pinctrl_desc u300_pmx_desc = {
static int __init u300_pmx_probe(struct platform_device *pdev)
{
- int ret;
struct u300_pmx *upmx;
struct resource *res;
+ int ret;
+ int i;
/* Create state holders etc for this driver */
upmx = devm_kzalloc(&pdev->dev, sizeof(*upmx), GFP_KERNEL);
@@ -1077,7 +1095,8 @@ static int __init u300_pmx_probe(struct platform_device *pdev)
}
/* We will handle a range of GPIO pins */
- pinctrl_add_gpio_range(upmx->pctl, &u300_gpio_range);
+ for (i = 0; i < ARRAY_SIZE(u300_gpio_ranges); i++)
+ pinctrl_add_gpio_range(upmx->pctl, &u300_gpio_ranges[i]);
platform_set_drvdata(pdev, upmx);
@@ -1099,8 +1118,10 @@ out_no_resource:
static int __exit u300_pmx_remove(struct platform_device *pdev)
{
struct u300_pmx *upmx = platform_get_drvdata(pdev);
+ int i;
- pinctrl_remove_gpio_range(upmx->pctl, &u300_gpio_range);
+ for (i = 0; i < ARRAY_SIZE(u300_gpio_ranges); i++)
+ pinctrl_remove_gpio_range(upmx->pctl, &u300_gpio_ranges[i]);
pinctrl_unregister(upmx->pctl);
iounmap(upmx->virtbase);
release_mem_region(upmx->phybase, upmx->physize);
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c
index a5467f8709e9..a76a348321bb 100644
--- a/drivers/pinctrl/pinmux.c
+++ b/drivers/pinctrl/pinmux.c
@@ -21,6 +21,7 @@
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
+#include <linux/string.h>
#include <linux/sysfs.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
@@ -32,12 +33,8 @@
static DEFINE_MUTEX(pinmux_list_mutex);
static LIST_HEAD(pinmux_list);
-/* List of pinmux hogs */
-static DEFINE_MUTEX(pinmux_hoglist_mutex);
-static LIST_HEAD(pinmux_hoglist);
-
-/* Global pinmux maps, we allow one set only */
-static struct pinmux_map const *pinmux_maps;
+/* Global pinmux maps */
+static struct pinmux_map *pinmux_maps;
static unsigned pinmux_maps_num;
/**
@@ -98,41 +95,35 @@ struct pinmux_hog {
* @function: a functional name to give to this pin, passed to the driver
* so it knows what function to mux in, e.g. the string "gpioNN"
* means that you want to mux in the pin for use as GPIO number NN
- * @gpio: if this request concerns a single GPIO pin
* @gpio_range: the range matching the GPIO pin if this is a request for a
* single GPIO pin
*/
static int pin_request(struct pinctrl_dev *pctldev,
- int pin, const char *function, bool gpio,
+ int pin, const char *function,
struct pinctrl_gpio_range *gpio_range)
{
struct pin_desc *desc;
const struct pinmux_ops *ops = pctldev->desc->pmxops;
int status = -EINVAL;
- dev_dbg(&pctldev->dev, "request pin %d for %s\n", pin, function);
-
- if (!pin_is_valid(pctldev, pin)) {
- dev_err(&pctldev->dev, "pin is invalid\n");
- return -EINVAL;
- }
-
- if (!function) {
- dev_err(&pctldev->dev, "no function name given\n");
- return -EINVAL;
- }
+ dev_dbg(pctldev->dev, "request pin %d for %s\n", pin, function);
desc = pin_desc_get(pctldev, pin);
if (desc == NULL) {
- dev_err(&pctldev->dev,
+ dev_err(pctldev->dev,
"pin is not registered so it cannot be requested\n");
goto out;
}
+ if (!function) {
+ dev_err(pctldev->dev, "no function name given\n");
+ return -EINVAL;
+ }
+
spin_lock(&desc->lock);
if (desc->mux_function) {
spin_unlock(&desc->lock);
- dev_err(&pctldev->dev,
+ dev_err(pctldev->dev,
"pin already requested\n");
goto out;
}
@@ -141,7 +132,7 @@ static int pin_request(struct pinctrl_dev *pctldev,
/* Let each pin increase references to this module */
if (!try_module_get(pctldev->owner)) {
- dev_err(&pctldev->dev,
+ dev_err(pctldev->dev,
"could not increase module refcount for pin %d\n",
pin);
status = -EINVAL;
@@ -152,7 +143,7 @@ static int pin_request(struct pinctrl_dev *pctldev,
* If there is no kind of request function for the pin we just assume
* we got it by default and proceed.
*/
- if (gpio && ops->gpio_request_enable)
+ if (gpio_range && ops->gpio_request_enable)
/* This requests and enables a single GPIO pin */
status = ops->gpio_request_enable(pctldev, gpio_range, pin);
else if (ops->request)
@@ -161,7 +152,7 @@ static int pin_request(struct pinctrl_dev *pctldev,
status = 0;
if (status)
- dev_err(&pctldev->dev, "->request on device %s failed "
+ dev_err(pctldev->dev, "->request on device %s failed "
"for pin %d\n",
pctldev->desc->name, pin);
out_free_pin:
@@ -172,7 +163,7 @@ out_free_pin:
}
out:
if (status)
- dev_err(&pctldev->dev, "pin-%d (%s) status %d\n",
+ dev_err(pctldev->dev, "pin-%d (%s) status %d\n",
pin, function ? : "?", status);
return status;
@@ -182,34 +173,52 @@ out:
* pin_free() - release a single muxed in pin so something else can be muxed
* @pctldev: pin controller device handling this pin
* @pin: the pin to free
- * @free_func: whether to free the pin's assigned function name string
+ * @gpio_range: the range matching the GPIO pin if this is a request for a
+ * single GPIO pin
+ *
+ * This function returns a pointer to the function name in use. This is used
+ * for callers that dynamically allocate a function name so it can be freed
+ * once the pin is free. This is done for GPIO request functions.
*/
-static void pin_free(struct pinctrl_dev *pctldev, int pin, int free_func)
+static const char *pin_free(struct pinctrl_dev *pctldev, int pin,
+ struct pinctrl_gpio_range *gpio_range)
{
const struct pinmux_ops *ops = pctldev->desc->pmxops;
struct pin_desc *desc;
+ const char *func;
desc = pin_desc_get(pctldev, pin);
if (desc == NULL) {
- dev_err(&pctldev->dev,
+ dev_err(pctldev->dev,
"pin is not registered so it cannot be freed\n");
- return;
+ return NULL;
}
- if (ops->free)
+ /*
+ * If there is no kind of request function for the pin we just assume
+ * we got it by default and proceed.
+ */
+ if (gpio_range && ops->gpio_disable_free)
+ ops->gpio_disable_free(pctldev, gpio_range, pin);
+ else if (ops->free)
ops->free(pctldev, pin);
spin_lock(&desc->lock);
- if (free_func)
- kfree(desc->mux_function);
+ func = desc->mux_function;
desc->mux_function = NULL;
spin_unlock(&desc->lock);
module_put(pctldev->owner);
+
+ return func;
}
/**
* pinmux_request_gpio() - request a single pin to be muxed in as GPIO
* @gpio: the GPIO pin number from the GPIO subsystem number space
+ *
+ * This function should *ONLY* be used from gpiolib-based GPIO drivers,
+ * as part of their gpio_request() semantics, platforms and individual drivers
+ * shall *NOT* request GPIO pins to be muxed in.
*/
int pinmux_request_gpio(unsigned gpio)
{
@@ -225,7 +234,7 @@ int pinmux_request_gpio(unsigned gpio)
return -EINVAL;
/* Convert to the pin controllers number space */
- pin = gpio - range->base;
+ pin = gpio - range->base + range->pin_base;
/* Conjure some name stating what chip and pin this is taken by */
snprintf(gpiostr, 15, "%s:%d", range->name, gpio);
@@ -234,7 +243,7 @@ int pinmux_request_gpio(unsigned gpio)
if (!function)
return -EINVAL;
- ret = pin_request(pctldev, pin, function, true, range);
+ ret = pin_request(pctldev, pin, function, range);
if (ret < 0)
kfree(function);
@@ -245,6 +254,10 @@ EXPORT_SYMBOL_GPL(pinmux_request_gpio);
/**
* pinmux_free_gpio() - free a single pin, currently used as GPIO
* @gpio: the GPIO pin number from the GPIO subsystem number space
+ *
+ * This function should *ONLY* be used from gpiolib-based GPIO drivers,
+ * as part of their gpio_free() semantics, platforms and individual drivers
+ * shall *NOT* request GPIO pins to be muxed out.
*/
void pinmux_free_gpio(unsigned gpio)
{
@@ -252,53 +265,108 @@ void pinmux_free_gpio(unsigned gpio)
struct pinctrl_gpio_range *range;
int ret;
int pin;
+ const char *func;
ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range);
if (ret)
return;
/* Convert to the pin controllers number space */
- pin = gpio - range->base;
+ pin = gpio - range->base + range->pin_base;
- pin_free(pctldev, pin, true);
+ func = pin_free(pctldev, pin, range);
+ kfree(func);
}
EXPORT_SYMBOL_GPL(pinmux_free_gpio);
+static int pinmux_gpio_direction(unsigned gpio, bool input)
+{
+ struct pinctrl_dev *pctldev;
+ struct pinctrl_gpio_range *range;
+ const struct pinmux_ops *ops;
+ int ret;
+ int pin;
+
+ ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range);
+ if (ret)
+ return ret;
+
+ ops = pctldev->desc->pmxops;
+
+ /* Convert to the pin controllers number space */
+ pin = gpio - range->base + range->pin_base;
+
+ if (ops->gpio_set_direction)
+ ret = ops->gpio_set_direction(pctldev, range, pin, input);
+ else
+ ret = 0;
+
+ return ret;
+}
+
+/**
+ * pinmux_gpio_direction_input() - request a GPIO pin to go into input mode
+ * @gpio: the GPIO pin number from the GPIO subsystem number space
+ *
+ * This function should *ONLY* be used from gpiolib-based GPIO drivers,
+ * as part of their gpio_direction_input() semantics, platforms and individual
+ * drivers shall *NOT* touch pinmux GPIO calls.
+ */
+int pinmux_gpio_direction_input(unsigned gpio)
+{
+ return pinmux_gpio_direction(gpio, true);
+}
+EXPORT_SYMBOL_GPL(pinmux_gpio_direction_input);
+
+/**
+ * pinmux_gpio_direction_output() - request a GPIO pin to go into output mode
+ * @gpio: the GPIO pin number from the GPIO subsystem number space
+ *
+ * This function should *ONLY* be used from gpiolib-based GPIO drivers,
+ * as part of their gpio_direction_output() semantics, platforms and individual
+ * drivers shall *NOT* touch pinmux GPIO calls.
+ */
+int pinmux_gpio_direction_output(unsigned gpio)
+{
+ return pinmux_gpio_direction(gpio, false);
+}
+EXPORT_SYMBOL_GPL(pinmux_gpio_direction_output);
+
/**
* pinmux_register_mappings() - register a set of pinmux mappings
- * @maps: the pinmux mappings table to register
+ * @maps: the pinmux mappings table to register, this should be marked with
+ * __initdata so it can be discarded after boot, this function will
+ * perform a shallow copy for the mapping entries.
* @num_maps: the number of maps in the mapping table
*
* Only call this once during initialization of your machine, the function is
* tagged as __init and won't be callable after init has completed. The map
* passed into this function will be owned by the pinmux core and cannot be
- * free:d.
+ * freed.
*/
int __init pinmux_register_mappings(struct pinmux_map const *maps,
unsigned num_maps)
{
+ void *tmp_maps;
int i;
- if (pinmux_maps != NULL) {
- pr_err("pinmux mappings already registered, you can only "
- "register one set of maps\n");
- return -EINVAL;
- }
-
pr_debug("add %d pinmux maps\n", num_maps);
+
+ /* First sanity check the new mapping */
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;
}
+
if (!maps[i].ctrl_dev && !maps[i].ctrl_dev_name) {
pr_err("failed to register map %s (%d): "
"no pin control device given\n",
maps[i].name, i);
return -EINVAL;
}
+
if (!maps[i].function) {
pr_err("failed to register map %s (%d): "
"no function ID given\n", maps[i].name, i);
@@ -315,9 +383,30 @@ int __init pinmux_register_mappings(struct pinmux_map const *maps,
maps[i].function);
}
- pinmux_maps = maps;
- pinmux_maps_num = num_maps;
+ /*
+ * Make a copy of the map array - string pointers will end up in the
+ * kernel const section anyway so these do not need to be deep copied.
+ */
+ if (!pinmux_maps_num) {
+ /* On first call, just copy them */
+ tmp_maps = kmemdup(maps,
+ sizeof(struct pinmux_map) * num_maps,
+ GFP_KERNEL);
+ if (!tmp_maps)
+ return -ENOMEM;
+ } else {
+ /* Subsequent calls, reallocate array to new size */
+ size_t oldsize = sizeof(struct pinmux_map) * pinmux_maps_num;
+ size_t newsize = sizeof(struct pinmux_map) * num_maps;
+
+ tmp_maps = krealloc(pinmux_maps, oldsize + newsize, GFP_KERNEL);
+ if (!tmp_maps)
+ return -ENOMEM;
+ memcpy((tmp_maps + oldsize), maps, newsize);
+ }
+ pinmux_maps = tmp_maps;
+ pinmux_maps_num += num_maps;
return 0;
}
@@ -345,14 +434,14 @@ static int acquire_pins(struct pinctrl_dev *pctldev,
if (ret)
return ret;
- dev_dbg(&pctldev->dev, "requesting the %u pins from group %u\n",
+ dev_dbg(pctldev->dev, "requesting the %u pins from group %u\n",
num_pins, group_selector);
/* Try to allocate all pins in this group, one by one */
for (i = 0; i < num_pins; i++) {
- ret = pin_request(pctldev, pins[i], func, false, NULL);
+ ret = pin_request(pctldev, pins[i], func, NULL);
if (ret) {
- dev_err(&pctldev->dev,
+ dev_err(pctldev->dev,
"could not get pin %d for function %s "
"on device %s - conflicting mux mappings?\n",
pins[i], func ? : "(undefined)",
@@ -360,7 +449,7 @@ static int acquire_pins(struct pinctrl_dev *pctldev,
/* On error release all taken pins */
i--; /* this pin just failed */
for (; i >= 0; i--)
- pin_free(pctldev, pins[i], false);
+ pin_free(pctldev, pins[i], NULL);
return -ENODEV;
}
}
@@ -384,44 +473,13 @@ static void release_pins(struct pinctrl_dev *pctldev,
ret = pctlops->get_group_pins(pctldev, group_selector,
&pins, &num_pins);
if (ret) {
- dev_err(&pctldev->dev, "could not get pins to release for "
+ dev_err(pctldev->dev, "could not get pins to release for "
"group selector %d\n",
group_selector);
return;
}
for (i = 0; i < num_pins; i++)
- pin_free(pctldev, pins[i], false);
-}
-
-/**
- * pinmux_get_group_selector() - returns the group selector for a group
- * @pctldev: the pin controller handling the group
- * @pin_group: the pin group to look up
- */
-static int pinmux_get_group_selector(struct pinctrl_dev *pctldev,
- const char *pin_group)
-{
- const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
- unsigned group_selector = 0;
-
- while (pctlops->list_groups(pctldev, group_selector) >= 0) {
- const char *gname = pctlops->get_group_name(pctldev,
- group_selector);
- if (!strcmp(gname, pin_group)) {
- dev_dbg(&pctldev->dev,
- "found group selector %u for %s\n",
- group_selector,
- pin_group);
- return group_selector;
- }
-
- group_selector++;
- }
-
- dev_err(&pctldev->dev, "does not have pin group %s\n",
- pin_group);
-
- return -EINVAL;
+ pin_free(pctldev, pins[i], NULL);
}
/**
@@ -465,9 +523,9 @@ static int pinmux_check_pin_group(struct pinctrl_dev *pctldev,
return ret;
if (num_groups < 1)
return -EINVAL;
- ret = pinmux_get_group_selector(pctldev, groups[0]);
+ ret = pinctrl_get_group_selector(pctldev, groups[0]);
if (ret < 0) {
- dev_err(&pctldev->dev,
+ 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),
@@ -476,7 +534,7 @@ static int pinmux_check_pin_group(struct pinctrl_dev *pctldev,
}
if (num_groups > 1)
- dev_dbg(&pctldev->dev,
+ dev_dbg(pctldev->dev,
"function %s support more than one group, "
"default-selecting first group %s (%d)\n",
pmxops->get_function_name(pctldev, func_selector),
@@ -486,13 +544,13 @@ static int pinmux_check_pin_group(struct pinctrl_dev *pctldev,
return ret;
}
- dev_dbg(&pctldev->dev,
+ dev_dbg(pctldev->dev,
"check if we have pin group %s on controller %s\n",
pin_group, pinctrl_dev_get_name(pctldev));
- ret = pinmux_get_group_selector(pctldev, pin_group);
+ ret = pinctrl_get_group_selector(pctldev, pin_group);
if (ret < 0) {
- dev_dbg(&pctldev->dev,
+ dev_dbg(pctldev->dev,
"%s does not support pin group %s with function %s\n",
pinctrl_dev_get_name(pctldev),
pin_group,
@@ -569,7 +627,7 @@ static int pinmux_enable_muxmap(struct pinctrl_dev *pctldev,
*/
if (pmx->pctldev && pmx->pctldev != pctldev) {
- dev_err(&pctldev->dev,
+ dev_err(pctldev->dev,
"different pin control devices given for device %s, "
"function %s\n",
devname,
@@ -592,7 +650,7 @@ static int pinmux_enable_muxmap(struct pinctrl_dev *pctldev,
*/
if (pmx->func_selector != UINT_MAX &&
pmx->func_selector != func_selector) {
- dev_err(&pctldev->dev,
+ dev_err(pctldev->dev,
"dual function defines in the map for device %s\n",
devname);
return -EINVAL;
@@ -698,7 +756,7 @@ struct pinmux *pinmux_get(struct device *dev, const char *name)
}
pr_debug("in map, found pctldev %s to handle function %s",
- dev_name(&pctldev->dev), map->function);
+ dev_name(pctldev->dev), map->function);
/*
@@ -874,7 +932,7 @@ static int pinmux_hog_map(struct pinctrl_dev *pctldev,
* without any problems, so then we can hog pinmuxes for
* all devices that just want a static pin mux at this point.
*/
- dev_err(&pctldev->dev, "map %s wants to hog a non-system "
+ dev_err(pctldev->dev, "map %s wants to hog a non-system "
"pinmux, this is not going to work\n", map->name);
return -EINVAL;
}
@@ -886,7 +944,7 @@ static int pinmux_hog_map(struct pinctrl_dev *pctldev,
pmx = pinmux_get(NULL, map->name);
if (IS_ERR(pmx)) {
kfree(hog);
- dev_err(&pctldev->dev,
+ dev_err(pctldev->dev,
"could not get the %s pinmux mapping for hogging\n",
map->name);
return PTR_ERR(pmx);
@@ -896,7 +954,7 @@ static int pinmux_hog_map(struct pinctrl_dev *pctldev,
if (ret) {
pinmux_put(pmx);
kfree(hog);
- dev_err(&pctldev->dev,
+ dev_err(pctldev->dev,
"could not enable the %s pinmux mapping for hogging\n",
map->name);
return ret;
@@ -905,7 +963,7 @@ static int pinmux_hog_map(struct pinctrl_dev *pctldev,
hog->map = map;
hog->pmx = pmx;
- dev_info(&pctldev->dev, "hogged map %s, function %s\n", map->name,
+ dev_info(pctldev->dev, "hogged map %s, function %s\n", map->name,
map->function);
mutex_lock(&pctldev->pinmux_hogs_lock);
list_add(&hog->node, &pctldev->pinmux_hogs);
@@ -924,7 +982,7 @@ static int pinmux_hog_map(struct pinctrl_dev *pctldev,
*/
int pinmux_hog_maps(struct pinctrl_dev *pctldev)
{
- struct device *dev = &pctldev->dev;
+ struct device *dev = pctldev->dev;
const char *devname = dev_name(dev);
int ret;
int i;
@@ -948,7 +1006,7 @@ int pinmux_hog_maps(struct pinctrl_dev *pctldev)
}
/**
- * pinmux_hog_maps() - unhog specific map entries on controller device
+ * pinmux_unhog_maps() - unhog specific map entries on controller device
* @pctldev: the pin control device to unhog entries on
*/
void pinmux_unhog_maps(struct pinctrl_dev *pctldev)
@@ -1005,18 +1063,19 @@ static int pinmux_functions_show(struct seq_file *s, void *what)
static int pinmux_pins_show(struct seq_file *s, void *what)
{
struct pinctrl_dev *pctldev = s->private;
- unsigned pin;
+ unsigned i, pin;
seq_puts(s, "Pinmux settings per pin\n");
seq_puts(s, "Format: pin (name): pinmuxfunction\n");
- /* The highest pin number need to be included in the loop, thus <= */
- for (pin = 0; pin <= pctldev->desc->maxpin; pin++) {
+ /* The pin number can be retrived from the pin controller descriptor */
+ for (i = 0; i < pctldev->desc->npins; i++) {
struct pin_desc *desc;
+ pin = pctldev->desc->pins[i].number;
desc = pin_desc_get(pctldev, pin);
- /* Pin space may be sparse */
+ /* Skip if we cannot search the pin */
if (desc == NULL)
continue;
OpenPOWER on IntegriCloud