Commit d8f388d8 authored by David Brownell's avatar David Brownell Committed by Linus Torvalds

gpio: sysfs interface

This adds a simple sysfs interface for GPIOs.

    /sys/class/gpio
    	/export ... asks the kernel to export a GPIO to userspace
    	/unexport ... to return a GPIO to the kernel
        /gpioN ... for each exported GPIO #N
	    /value ... always readable, writes fail for input GPIOs
	    /direction ... r/w as: in, out (default low); write high, low
	/gpiochipN ... for each gpiochip; #N is its first GPIO
	    /base ... (r/o) same as N
	    /label ... (r/o) descriptive, not necessarily unique
	    /ngpio ... (r/o) number of GPIOs; numbered N .. N+(ngpio - 1)

GPIOs claimed by kernel code may be exported by its owner using a new
gpio_export() call, which should be most useful for driver debugging.
Such exports may optionally be done without a "direction" attribute.

Userspace may ask to take over a GPIO by writing to a sysfs control file,
helping to cope with incomplete board support or other "one-off"
requirements that don't merit full kernel support:

  echo 23 > /sys/class/gpio/export
	... will gpio_request(23, "sysfs") and gpio_export(23);
	use /sys/class/gpio/gpio-23/direction to (re)configure it,
	when that GPIO can be used as both input and output.
  echo 23 > /sys/class/gpio/unexport
	... will gpio_free(23), when it was exported as above

The extra D-space footprint is a few hundred bytes, except for the sysfs
resources associated with each exported GPIO.  The additional I-space
footprint is about two thirds of the current size of gpiolib (!).  Since
no /dev node creation is involved, no "udev" support is needed.

Related changes:

  * This adds a device pointer to "struct gpio_chip".  When GPIO
    providers initialize that, sysfs gpio class devices become children of
    that device instead of being "virtual" devices.

  * The (few) gpio_chip providers which have such a device node have
    been updated.

  * Some gpio_chip drivers also needed to update their module "owner"
    field ...  for which missing kerneldoc was added.

  * Some gpio_chips don't support input GPIOs.  Those GPIOs are now
    flagged appropriately when the chip is registered.

Based on previous patches, and discussion both on and off LKML.

A Documentation/ABI/testing/sysfs-gpio update is ready to submit once this
merges to mainline.

[akpm@linux-foundation.org: a few maintenance build fixes]
Signed-off-by: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
Cc: Guennadi Liakhovetski <g.liakhovetski@pengutronix.de>
Cc: Greg KH <greg@kroah.com>
Cc: Kay Sievers <kay.sievers@vrfy.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 8b6dd986
...@@ -347,15 +347,12 @@ necessarily be nonportable. ...@@ -347,15 +347,12 @@ necessarily be nonportable.
Dynamic definition of GPIOs is not currently standard; for example, as Dynamic definition of GPIOs is not currently standard; for example, as
a side effect of configuring an add-on board with some GPIO expanders. a side effect of configuring an add-on board with some GPIO expanders.
These calls are purely for kernel space, but a userspace API could be built
on top of them.
GPIO implementor's framework (OPTIONAL) GPIO implementor's framework (OPTIONAL)
======================================= =======================================
As noted earlier, there is an optional implementation framework making it As noted earlier, there is an optional implementation framework making it
easier for platforms to support different kinds of GPIO controller using easier for platforms to support different kinds of GPIO controller using
the same programming interface. the same programming interface. This framework is called "gpiolib".
As a debugging aid, if debugfs is available a /sys/kernel/debug/gpio file As a debugging aid, if debugfs is available a /sys/kernel/debug/gpio file
will be found there. That will list all the controllers registered through will be found there. That will list all the controllers registered through
...@@ -439,4 +436,120 @@ becomes available. That may mean the device should not be registered until ...@@ -439,4 +436,120 @@ becomes available. That may mean the device should not be registered until
calls for that GPIO can work. One way to address such dependencies is for calls for that GPIO can work. One way to address such dependencies is for
such gpio_chip controllers to provide setup() and teardown() callbacks to such gpio_chip controllers to provide setup() and teardown() callbacks to
board specific code; those board specific callbacks would register devices board specific code; those board specific callbacks would register devices
once all the necessary resources are available. once all the necessary resources are available, and remove them later when
the GPIO controller device becomes unavailable.
Sysfs Interface for Userspace (OPTIONAL)
========================================
Platforms which use the "gpiolib" implementors framework may choose to
configure a sysfs user interface to GPIOs. This is different from the
debugfs interface, since it provides control over GPIO direction and
value instead of just showing a gpio state summary. Plus, it could be
present on production systems without debugging support.
Given approprate hardware documentation for the system, userspace could
know for example that GPIO #23 controls the write protect line used to
protect boot loader segments in flash memory. System upgrade procedures
may need to temporarily remove that protection, first importing a GPIO,
then changing its output state, then updating the code before re-enabling
the write protection. In normal use, GPIO #23 would never be touched,
and the kernel would have no need to know about it.
Again depending on appropriate hardware documentation, on some systems
userspace GPIO can be used to determine system configuration data that
standard kernels won't know about. And for some tasks, simple userspace
GPIO drivers could be all that the system really needs.
Note that standard kernel drivers exist for common "LEDs and Buttons"
GPIO tasks: "leds-gpio" and "gpio_keys", respectively. Use those
instead of talking directly to the GPIOs; they integrate with kernel
frameworks better than your userspace code could.
Paths in Sysfs
--------------
There are three kinds of entry in /sys/class/gpio:
- Control interfaces used to get userspace control over GPIOs;
- GPIOs themselves; and
- GPIO controllers ("gpio_chip" instances).
That's in addition to standard files including the "device" symlink.
The control interfaces are write-only:
/sys/class/gpio/
"export" ... Userspace may ask the kernel to export control of
a GPIO to userspace by writing its number to this file.
Example: "echo 19 > export" will create a "gpio19" node
for GPIO #19, if that's not requested by kernel code.
"unexport" ... Reverses the effect of exporting to userspace.
Example: "echo 19 > unexport" will remove a "gpio19"
node exported using the "export" file.
GPIO signals have paths like /sys/class/gpio/gpio42/ (for GPIO #42)
and have the following read/write attributes:
/sys/class/gpio/gpioN/
"direction" ... reads as either "in" or "out". This value may
normally be written. Writing as "out" defaults to
initializing the value as low. To ensure glitch free
operation, values "low" and "high" may be written to
configure the GPIO as an output with that initial value.
Note that this attribute *will not exist* if the kernel
doesn't support changing the direction of a GPIO, or
it was exported by kernel code that didn't explicitly
allow userspace to reconfigure this GPIO's direction.
"value" ... reads as either 0 (low) or 1 (high). If the GPIO
is configured as an output, this value may be written;
any nonzero value is treated as high.
GPIO controllers have paths like /sys/class/gpio/chipchip42/ (for the
controller implementing GPIOs starting at #42) and have the following
read-only attributes:
/sys/class/gpio/gpiochipN/
"base" ... same as N, the first GPIO managed by this chip
"label" ... provided for diagnostics (not always unique)
"ngpio" ... how many GPIOs this manges (N to N + ngpio - 1)
Board documentation should in most cases cover what GPIOs are used for
what purposes. However, those numbers are not always stable; GPIOs on
a daughtercard might be different depending on the base board being used,
or other cards in the stack. In such cases, you may need to use the
gpiochip nodes (possibly in conjunction with schematics) to determine
the correct GPIO number to use for a given signal.
Exporting from Kernel code
--------------------------
Kernel code can explicitly manage exports of GPIOs which have already been
requested using gpio_request():
/* export the GPIO to userspace */
int gpio_export(unsigned gpio, bool direction_may_change);
/* reverse gpio_export() */
void gpio_unexport();
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
signal direction may change. This helps drivers prevent userspace code
from accidentally clobbering important system state.
This explicit exporting can help with debugging (by making some kinds
of experiments easier), or can provide an always-there interface that's
suitable for documenting as part of a board support package.
...@@ -1488,6 +1488,9 @@ static int __init _omap_gpio_init(void) ...@@ -1488,6 +1488,9 @@ static int __init _omap_gpio_init(void)
bank->chip.set = gpio_set; bank->chip.set = gpio_set;
if (bank_is_mpuio(bank)) { if (bank_is_mpuio(bank)) {
bank->chip.label = "mpuio"; bank->chip.label = "mpuio";
#ifdef CONFIG_ARCH_OMAP1
bank->chip.dev = &omap_mpuio_device.dev;
#endif
bank->chip.base = OMAP_MPUIO(0); bank->chip.base = OMAP_MPUIO(0);
} else { } else {
bank->chip.label = "gpio"; bank->chip.label = "gpio";
......
...@@ -360,6 +360,8 @@ static int __init pio_probe(struct platform_device *pdev) ...@@ -360,6 +360,8 @@ static int __init pio_probe(struct platform_device *pdev)
pio->chip.label = pio->name; pio->chip.label = pio->name;
pio->chip.base = pdev->id * 32; pio->chip.base = pdev->id * 32;
pio->chip.ngpio = 32; pio->chip.ngpio = 32;
pio->chip.dev = &pdev->dev;
pio->chip.owner = THIS_MODULE;
pio->chip.direction_input = direction_input; pio->chip.direction_input = direction_input;
pio->chip.get = gpio_get; pio->chip.get = gpio_get;
......
...@@ -23,6 +23,21 @@ config DEBUG_GPIO ...@@ -23,6 +23,21 @@ config DEBUG_GPIO
slower. The diagnostics help catch the type of setup errors slower. The diagnostics help catch the type of setup errors
that are most common when setting up new platforms or boards. that are most common when setting up new platforms or boards.
config GPIO_SYSFS
bool "/sys/class/gpio/... (sysfs interface)"
depends on SYSFS && EXPERIMENTAL
help
Say Y here to add a sysfs interface for GPIOs.
This is mostly useful to work around omissions in a system's
kernel support. Those are common in custom and semicustom
hardware assembled using standard kernels with a minimum of
custom patches. In those cases, userspace code may import
a given GPIO from the kernel, if no kernel driver requested it.
Kernel drivers may also request that a particular GPIO be
exported to userspace; this can be useful when debugging.
# put expanders in the right section, in alphabetical order # put expanders in the right section, in alphabetical order
comment "I2C GPIO expanders:" comment "I2C GPIO expanders:"
......
This diff is collapsed.
...@@ -239,6 +239,7 @@ static int mcp23s08_probe(struct spi_device *spi) ...@@ -239,6 +239,7 @@ static int mcp23s08_probe(struct spi_device *spi)
mcp->chip.base = pdata->base; mcp->chip.base = pdata->base;
mcp->chip.ngpio = 8; mcp->chip.ngpio = 8;
mcp->chip.can_sleep = 1; mcp->chip.can_sleep = 1;
mcp->chip.dev = &spi->dev;
mcp->chip.owner = THIS_MODULE; mcp->chip.owner = THIS_MODULE;
spi_set_drvdata(spi, mcp); spi_set_drvdata(spi, mcp);
......
...@@ -188,6 +188,7 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios) ...@@ -188,6 +188,7 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
gc->base = chip->gpio_start; gc->base = chip->gpio_start;
gc->ngpio = gpios; gc->ngpio = gpios;
gc->label = chip->client->name; gc->label = chip->client->name;
gc->dev = &chip->client->dev;
gc->owner = THIS_MODULE; gc->owner = THIS_MODULE;
} }
......
...@@ -200,6 +200,7 @@ static int pcf857x_probe(struct i2c_client *client, ...@@ -200,6 +200,7 @@ static int pcf857x_probe(struct i2c_client *client,
gpio->chip.base = pdata->gpio_base; gpio->chip.base = pdata->gpio_base;
gpio->chip.can_sleep = 1; gpio->chip.can_sleep = 1;
gpio->chip.dev = &client->dev;
gpio->chip.owner = THIS_MODULE; gpio->chip.owner = THIS_MODULE;
/* NOTE: the OnSemi jlc1562b is also largely compatible with /* NOTE: the OnSemi jlc1562b is also largely compatible with
......
...@@ -636,6 +636,8 @@ static int tps65010_probe(struct i2c_client *client, ...@@ -636,6 +636,8 @@ static int tps65010_probe(struct i2c_client *client,
tps->outmask = board->outmask; tps->outmask = board->outmask;
tps->chip.label = client->name; tps->chip.label = client->name;
tps->chip.dev = &client->dev;
tps->chip.owner = THIS_MODULE;
tps->chip.set = tps65010_gpio_set; tps->chip.set = tps65010_gpio_set;
tps->chip.direction_output = tps65010_output; tps->chip.direction_output = tps65010_output;
......
...@@ -318,6 +318,8 @@ static int __init egpio_probe(struct platform_device *pdev) ...@@ -318,6 +318,8 @@ static int __init egpio_probe(struct platform_device *pdev)
ei->chip[i].dev = &(pdev->dev); ei->chip[i].dev = &(pdev->dev);
chip = &(ei->chip[i].chip); chip = &(ei->chip[i].chip);
chip->label = "htc-egpio"; chip->label = "htc-egpio";
chip->dev = &pdev->dev;
chip->owner = THIS_MODULE;
chip->get = egpio_get; chip->get = egpio_get;
chip->set = egpio_set; chip->set = egpio_set;
chip->direction_input = egpio_direction_input; chip->direction_input = egpio_direction_input;
......
...@@ -32,6 +32,8 @@ struct module; ...@@ -32,6 +32,8 @@ struct module;
/** /**
* struct gpio_chip - abstract a GPIO controller * struct gpio_chip - abstract a GPIO controller
* @label: for diagnostics * @label: for diagnostics
* @dev: optional device providing the GPIOs
* @owner: helps prevent removal of modules exporting active GPIOs
* @direction_input: configures signal "offset" as input, or returns error * @direction_input: configures signal "offset" as input, or returns error
* @get: returns value for signal "offset"; for output signals this * @get: returns value for signal "offset"; for output signals this
* returns either the value actually sensed, or zero * returns either the value actually sensed, or zero
...@@ -59,6 +61,7 @@ struct module; ...@@ -59,6 +61,7 @@ struct module;
*/ */
struct gpio_chip { struct gpio_chip {
char *label; char *label;
struct device *dev;
struct module *owner; struct module *owner;
int (*direction_input)(struct gpio_chip *chip, int (*direction_input)(struct gpio_chip *chip,
...@@ -74,6 +77,7 @@ struct gpio_chip { ...@@ -74,6 +77,7 @@ struct gpio_chip {
int base; int base;
u16 ngpio; u16 ngpio;
unsigned can_sleep:1; unsigned can_sleep:1;
unsigned exported:1;
}; };
extern const char *gpiochip_is_requested(struct gpio_chip *chip, extern const char *gpiochip_is_requested(struct gpio_chip *chip,
...@@ -108,7 +112,18 @@ extern void __gpio_set_value(unsigned gpio, int value); ...@@ -108,7 +112,18 @@ extern void __gpio_set_value(unsigned gpio, int value);
extern int __gpio_cansleep(unsigned gpio); extern int __gpio_cansleep(unsigned gpio);
#else #ifdef CONFIG_GPIO_SYSFS
/*
* A sysfs interface can be exported by individual drivers if they want,
* but more typically is configured entirely from userspace.
*/
extern int gpio_export(unsigned gpio, bool direction_may_change);
extern void gpio_unexport(unsigned gpio);
#endif /* CONFIG_GPIO_SYSFS */
#else /* !CONFIG_HAVE_GPIO_LIB */
static inline int gpio_is_valid(int number) static inline int gpio_is_valid(int number)
{ {
...@@ -137,6 +152,20 @@ static inline void gpio_set_value_cansleep(unsigned gpio, int value) ...@@ -137,6 +152,20 @@ static inline void gpio_set_value_cansleep(unsigned gpio, int value)
gpio_set_value(gpio, value); gpio_set_value(gpio, value);
} }
#endif #endif /* !CONFIG_HAVE_GPIO_LIB */
#ifndef CONFIG_GPIO_SYSFS
/* sysfs support is only available with gpiolib, where it's optional */
static inline int gpio_export(unsigned gpio, bool direction_may_change)
{
return -ENOSYS;
}
static inline void gpio_unexport(unsigned gpio)
{
}
#endif /* CONFIG_GPIO_SYSFS */
#endif /* _ASM_GENERIC_GPIO_H */ #endif /* _ASM_GENERIC_GPIO_H */
...@@ -79,6 +79,19 @@ static inline void gpio_set_value_cansleep(unsigned gpio, int value) ...@@ -79,6 +79,19 @@ static inline void gpio_set_value_cansleep(unsigned gpio, int value)
WARN_ON(1); WARN_ON(1);
} }
static inline int gpio_export(unsigned gpio, bool direction_may_change)
{
/* GPIO can never have been requested or set as {in,out}put */
WARN_ON(1);
return -EINVAL;
}
static inline void gpio_unexport(unsigned gpio)
{
/* GPIO can never have been exported */
WARN_ON(1);
}
static inline int gpio_to_irq(unsigned gpio) static inline int gpio_to_irq(unsigned gpio)
{ {
/* GPIO can never have been requested or set as input */ /* GPIO can never have been requested or set as input */
......
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