Commit a4177ee7 authored by Jani Nikula's avatar Jani Nikula Committed by Linus Torvalds

gpiolib: allow exported GPIO nodes to be named using sysfs links

Commit 926b663c (gpiolib: allow GPIOs to
be named) already provides naming on the chip level. This patch provides
more flexibility by allowing multiple names where ever in sysfs on a per
GPIO basis.

Adapted from David Brownell's comments on a similar concept:
http://lkml.org/lkml/2009/4/20/203.

[randy.dunlap@oracle.com: fix build for CONFIG_GENERIC_GPIO=n]
Signed-off-by: default avatarJani Nikula <ext-jani.1.nikula@nokia.com>
Acked-by: default avatarDavid Brownell <david-b@pacbell.net>
Cc: Daniel Silverstone <dsilvers@simtec.co.uk>
Signed-off-by: default avatarRandy Dunlap <randy.dunlap@oracle.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent d8c1acb1
...@@ -555,6 +555,11 @@ requested using gpio_request(): ...@@ -555,6 +555,11 @@ requested using gpio_request():
/* reverse gpio_export() */ /* reverse gpio_export() */
void gpio_unexport(); void gpio_unexport();
/* create a sysfs link to an exported GPIO node */
int gpio_export_link(struct device *dev, const char *name,
unsigned gpio)
After a kernel driver requests a GPIO, it may only be made available in After a kernel driver requests a GPIO, it may only be made available in
the sysfs interface by gpio_export(). The driver can control whether the the sysfs interface by gpio_export(). The driver can control whether the
signal direction may change. This helps drivers prevent userspace code signal direction may change. This helps drivers prevent userspace code
...@@ -563,3 +568,8 @@ from accidentally clobbering important system state. ...@@ -563,3 +568,8 @@ from accidentally clobbering important system state.
This explicit exporting can help with debugging (by making some kinds This explicit exporting can help with debugging (by making some kinds
of experiments easier), or can provide an always-there interface that's of experiments easier), or can provide an always-there interface that's
suitable for documenting as part of a board support package. suitable for documenting as part of a board support package.
After the GPIO has been exported, gpio_export_link() allows creating
symlinks from elsewhere in sysfs to the GPIO sysfs node. Drivers can
use this to provide the interface under their own device in sysfs with
a descriptive name.
...@@ -504,6 +504,51 @@ static int match_export(struct device *dev, void *data) ...@@ -504,6 +504,51 @@ static int match_export(struct device *dev, void *data)
return dev_get_drvdata(dev) == data; return dev_get_drvdata(dev) == data;
} }
/**
* gpio_export_link - create a sysfs link to an exported GPIO node
* @dev: device under which to create symlink
* @name: name of the symlink
* @gpio: gpio to create symlink to, already exported
*
* Set up a symlink from /sys/.../dev/name to /sys/class/gpio/gpioN
* node. Caller is responsible for unlinking.
*
* Returns zero on success, else an error.
*/
int gpio_export_link(struct device *dev, const char *name, unsigned gpio)
{
struct gpio_desc *desc;
int status = -EINVAL;
if (!gpio_is_valid(gpio))
goto done;
mutex_lock(&sysfs_lock);
desc = &gpio_desc[gpio];
if (test_bit(FLAG_EXPORT, &desc->flags)) {
struct device *tdev;
tdev = class_find_device(&gpio_class, NULL, desc, match_export);
if (tdev != NULL) {
status = sysfs_create_link(&dev->kobj, &tdev->kobj,
name);
} else {
status = -ENODEV;
}
}
mutex_unlock(&sysfs_lock);
done:
if (status)
pr_debug("%s: gpio%d status %d\n", __func__, gpio, status);
return status;
}
EXPORT_SYMBOL_GPL(gpio_export_link);
/** /**
* gpio_unexport - reverse effect of gpio_export() * gpio_unexport - reverse effect of gpio_export()
* @gpio: gpio to make unavailable * @gpio: gpio to make unavailable
......
...@@ -141,6 +141,8 @@ extern int __gpio_to_irq(unsigned gpio); ...@@ -141,6 +141,8 @@ extern int __gpio_to_irq(unsigned gpio);
* but more typically is configured entirely from userspace. * but more typically is configured entirely from userspace.
*/ */
extern int gpio_export(unsigned gpio, bool direction_may_change); extern int gpio_export(unsigned gpio, bool direction_may_change);
extern int gpio_export_link(struct device *dev, const char *name,
unsigned gpio);
extern void gpio_unexport(unsigned gpio); extern void gpio_unexport(unsigned gpio);
#endif /* CONFIG_GPIO_SYSFS */ #endif /* CONFIG_GPIO_SYSFS */
...@@ -185,6 +187,12 @@ static inline int gpio_export(unsigned gpio, bool direction_may_change) ...@@ -185,6 +187,12 @@ static inline int gpio_export(unsigned gpio, bool direction_may_change)
return -ENOSYS; return -ENOSYS;
} }
static inline int gpio_export_link(struct device *dev, const char *name,
unsigned gpio)
{
return -ENOSYS;
}
static inline void gpio_unexport(unsigned gpio) static inline void gpio_unexport(unsigned gpio)
{ {
} }
......
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/errno.h> #include <linux/errno.h>
struct device;
/* /*
* Some platforms don't support the GPIO programming interface. * Some platforms don't support the GPIO programming interface.
* *
...@@ -89,6 +91,15 @@ static inline int gpio_export(unsigned gpio, bool direction_may_change) ...@@ -89,6 +91,15 @@ static inline int gpio_export(unsigned gpio, bool direction_may_change)
return -EINVAL; return -EINVAL;
} }
static inline int gpio_export_link(struct device *dev, const char *name,
unsigned gpio)
{
/* GPIO can never have been exported */
WARN_ON(1);
return -EINVAL;
}
static inline void gpio_unexport(unsigned gpio) static inline void gpio_unexport(unsigned gpio)
{ {
/* GPIO can never have been exported */ /* GPIO can never have been exported */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment