All of lore.kernel.org
 help / color / mirror / Atom feed
* [patch/rfc 2.6.19-rc5] arch-neutral GPIO calls
@ 2006-11-11 23:41 David Brownell
  2006-11-12  1:27 ` H. Peter Anvin
                   ` (4 more replies)
  0 siblings, 5 replies; 103+ messages in thread
From: David Brownell @ 2006-11-11 23:41 UTC (permalink / raw)
  To: Linux Kernel list
  Cc: Andrew Morton, Andrew Victor, Bill Gatliff, Haavard Skinnemoen,
	jamey.hicks, Kevin Hilman, Nicolas Pitre, Russell King,
	Tony Lindgren

I know there have been discussions about standardizing GPIOs before,
but nothing quite "took".  One of the more recent ones was

  http://marc.theaimsgroup.com/?l=linux-kernel&m=110873454720555&w=2

Below, find what I think is a useful proposal, trivially implementable on
many ARMs (at91, omap, pxa, ep93xx, ixp2000, pnx4008, davinci, more) as well
as the new AVR32.

Compared to the proposal above, key differences include:

  - Only intended for use with "real" GPIOs that work from IRQ context;
    e.g. pins on a SOC that are controlled by chip register access.

  - Doesn't handle I2C or SPI based GPIOs.  I think we actually need
    a different API for those "message based" GPIOs, where synchronous
    get/set requires sleeping (and is thus unusable from IRQ context).
    That API could be used for "real" GPIOs; the converse is not true.

  - No IORESOURCE_GPIO resource type (could be added though).

  - Can be trivially implemented today, on many systems (see partial
    list above) ... no "provider" or gpiochip API necessary.

  - Provided in the form of a working patch, with sample implementation;
    known to be viable on multiple architectures and platforms.

  - Includes Documentation/gpio.txt

Comments?

- Dave


============================	CUT HERE
This defines a simple and minimalist convention for GPIO APIs, and an
implementation of it on one ARM platform (OMAP):

  - Documentation/gpio.txt ... describes things (read it)

  - include/asm-arm/gpio.h ... defines the ARM hook, which just punts
    to <asm/arch/gpio.h> for any implementation

  - include/asm-arm/arch-omap/gpio.h ... representative implementation
    as a wrapper around existing OMAP-specific GPIO calls

The immediate need for such a cross-architecture API convention is to support
drivers that work the same on AT91 ARM and AVR32 AP7000 chips, which embed many
of the same controllers but have different CPUs.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>


Index: osk/Documentation/gpio.txt
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ osk/Documentation/gpio.txt	2006-11-11 15:20:58.000000000 -0800
@@ -0,0 +1,233 @@
+GPIO Interfaces
+
+This provides an overview of GPIO access API conventions on Linux.
+
+
+What is a GPIO?
+===============
+A "General Purpose Input/Output" (GPIO) is a flexible software-controlled
+digital signal.  They are provided from many kinds of chip, and are familiar
+to Linux developers working with embedded and custom hardware.  Each GPIO
+represents a bit connected to a particular pin, or "ball" on Ball Grid Array
+(BGA) packages.  Board schematics show which external hardware connects to
+which GPIOs.  Drivers can be written generically, so that board setup code
+passes such pin configuration data to drivers.
+
+System-on-Chip (SOC) processors heavily rely on GPIOs.  In many cases, every
+non-dedicated pin can be configured as a GPIO; and most chips have at least
+several dozen of them.  Programmable logic devices (like FPGAs) can easily
+provide GPIOs, and I2C-connected chips like power managers, audio codecs,
+and "GPIO Expanders" often have a few such pins to help with pin scarcity on
+SOCs.  Most PC southbridges have a few dozen GPIO-capable pins.
+
+The exact capabilities of GPIOs vary between systems.  Common options:
+
+  - Output values are writable (high=1, low=0).  Some chips also have
+    options about how that value is driven, so that for example only one
+    value might be driven ... supporting "wire-OR" and similar schemes
+    for the other value.
+
+  - Input values are likewise readable (1, 0).  Some chips support readback
+    of pins configured as "output", which is very useful in such "wire-OR"
+    cases (to support bidirectional signaling).  GPIO controllers may have
+    input de-glitch logic, sometimes with software controls.
+
+  - Inputs can often be used as IRQ signals, often edge triggered but
+    sometimes level triggered.  Such IRQs may be configurable as system
+    wakeup events, to wake the system from a low power state.
+
+  - Usually a GPIO will be configurable as either input or output, as needed
+    by different product boards; single direction ones exist too.
+
+On a given board each GPIO is used for one specific purpose like monitoring
+MMC/SD card insertion/removal, detecting card writeprotect status, driving
+a LED, configuring a transceiver, and so on.
+
+
+What are the Linux GPIO API conventions?
+========================================
+Note that this is called a "convention" because you don't need to do it this
+way, and it's no crime if you don't.  There **are** cases where portability
+is not the main issue; GPIOs are often used for the kind of board-specific
+glue logic that may even change between board revisions, and can't ever be
+used on a board that's wired differently.  Also, see the notes later on what
+these conventions omit.
+
+That said, if the convention is supported on their platform, drivers should
+probably use it when possible:
+
+	#include <asm/gpio.h>
+	
+If you stick to this convention then it'll be easier for other developers to
+see what your code is doing, and maintain it.
+
+
+Identifying GPIOs
+-----------------
+GPIOs are identified by unsigned integers in the range 0..MAX_INT.  That
+reserves "negative" numbers for other purposes like marking signals as
+"not available on this board", or indicating faults.
+
+A given platform defines how it uses those integers.  So for example one
+might not use "GPIO 0", instead using numbers 32-159.  Another platform
+could use numbers 0..63 with one set of GPIO controllers, 64-79 with a
+different type of GPIO controller, and 80-95 with an FPGA used with one
+particular board family.  GPIO numbers are not the same as IRQ numbers;
+see below for calls mapping between the two namespaces.
+
+A given platform may want to define symbols corresponding to GPIO lines,
+primarily for use in board-specific setup code. Most drivers should use
+GPIO numbers passed to them from that setup code, using platform_data to
+hold board-specific pin configuration data (along with other board
+specific data they need).
+
+
+Using GPIOs
+-----------
+One of the first things to do with a GPIO, often in board setup code when
+setting up a platform_device using the GPIO, is mark its direction:
+
+	/* set as input or output, returning 0 or negative errno */
+	int gpio_direction_input(unsigned gpio);
+	int gpio_direction_output(unsigned gpio);
+
+The return value is zero for success, else a negative errno; it must be
+checked, since the main calls don't have error returns.
+
+Setting the direction can fail if the GPIO number is invalid, or when
+that particular GPIO can't be used in that mode.  It's generally a bad
+idea to rely on boot firmware to have set the direction correctly, since
+it probably wasn't validated to do more than boot Linux.  (Similarly,
+that board setup code probably needs to multiplex that pin as a GPIO,
+and arrange pullups/pulldowns appropriately.)
+
+Driver code will then use this either as an input, or an output.  These
+calls can safely be issued from inside IRQ handlers; they don't sleep.
+
+	/* GPIO INPUT:  return zero or nonzero */
+	int gpio_get_value(unsigned gpio);
+
+	/* GPIO OUTPUT */
+	void gpio_set_value(unsigned gpio, int value);
+
+The get/set calls have no error returns because "invalid GPIO" would have
+been reported earlier in gpio_set_direction().  The values are boolean,
+zero for low, nonzero for high.  When reading the value of an output pin,
+the value returned should be what's seen on the pin ... that won't always
+match the specified output value, because of issues including wire-OR and
+output latencies.
+
+Platform-specific implementations are encouraged to optimise the two
+calls to access the GPIO value in cases where the GPIO number (and for
+output, value) are constant.  It's normal for them to need only a couple
+of instructions in such cases (reading or writing a hardware register),
+and not to need spinlocks.  Such optimized calls can make bitbanging
+applications a lot more efficient (in both space and time) than spending
+dozens of instructions on subroutine calls.
+
+
+Claiming and Releasing GPIOs (OPTIONAL)
+---------------------------------------
+To help catch system configuration errors, two calls are defined.
+However, many platforms don't currently support this mechanism.
+
+	/* request GPIO, returning 0 or negative errno.
+	 * non-null labels may be useful for diagnostics.
+	 */
+	int gpio_request(unsigned gpio, const char *label);
+
+	/* release previously-claimed GPIO */
+	void gpio_free(unsigned gpio);
+
+Passing invalid GPIO numbers to gpio_request() will fail, as will requesting
+GPIOs that have already been claimed with that call.  The return value of
+gpio_request() must be checked.
+
+These APIs serve two basic purposes.  One is marking the signals which
+are actually in use as GPIOs, for better diagnostics; systems may have
+several hundred potential GPIOs, but often only a dozen are used on any
+given board.  Another is to catch confusion between drivers, reporting
+errors when drivers wrongly think they have exclusive use of that signal.
+
+These two calls are optional because not not all current Linux platforms
+offer such functionality in their GPIO support; a valid implementation
+could return success for all gpio_request() calls.  Unlike the other calls,
+the state they represent doesn't normally match anything from a hardware
+register; it's just a software bitmap which clearly is not necessary for
+correct operation of hardware or (bug free) drivers.
+
+Note that requesting a GPIO does NOT cause it to be configured in any
+way; it just marks that GPIO as in use.  Separate code must handle any
+pin setup (e.g. controlling which pin the GPIO uses, pullup/pulldown).
+
+
+Identifying GPIO IRQs
+---------------------
+GPIO numbers are unsigned integers; so are IRQ numbers.  These make up
+two logically distinct namespaces (GPIO 0 need not use IRQ 0).  You can
+map between them using calls like:
+
+	/* map GPIO numbers to IRQ numbers */
+	int gpio_to_irq(unsigned gpio);
+
+	/* map IRQ numbers to GPIO numbers */
+	int irq_to_gpio(unsigned irq);
+
+Those return either the corresponding number in the other namespace, or
+else a negative errno code if the mapping can't be done.  (For example,
+some GPIOs can't used as IRQs.)  It is an unchecked error to use a GPIO
+number that hasn't been marked as an input using gpio_set_direction(), or
+to use an IRQ number that didn't originally come from gpio_to_irq().
+
+These two mapping calls are expected to cost on the order of a single
+addition or subtraction.
+
+Non-error values returned from gpio_to_irq() can be passed to request_irq()
+or free_irq().  They will often be stored into IRQ resources for platform
+devices, by the board-specific initialization code.  Note that IRQ trigger
+options are part of the IRQ API, e.g. IRQF_TRIGGER_FALLING, as are system
+wakeup capabilities.
+
+Non-error values returned from irq_to_gpio() would most commonly be used
+with gpio_get_value().
+
+
+
+What do these conventions omit?
+===============================
+These conventions address least-common-denominator functionality, and
+nonportable features are left as platform-specific (but also accessible
+through <asm/gpio.h> inclusion).  Some of these may also be configuration
+dependent; the hardware may support reading or writing GPIOs in gangs,
+but only for GPIOs sharing the same bank.  (GPIOs are commonly grouped
+in banks of 16 or 32, with a given SOC having several such banks.)
+
+One of the biggest things these conventions omit is pin multiplexing, since
+this is highly chip-specific and nonportable.  One platform might not need
+explicit multiplexing; another might have just two options for use of any
+given pin; another might have eight options per pin; another might be able
+to switch a given GPIO to any of several pins.  (Yes, those examples all
+come from systems that run Linux today.)
+
+Related to multiplexing is configuration and enabling of the pullups or
+pulldowns integrated on some platforms.  Not all platforms support them,
+or support them in the same way; and any given board may use external
+pullups (or pulldowns) so that the on-chip ones should not be used.
+
+There are other system-specific mechanisms that are not specified here,
+like the aforementioned options for input de-glitching and wire-OR output,
+or ganged I/O.  Code relying on them will by definition be nonportable.
+
+GPIOs accessed through serial bus chips, like I2C GPIO expanders, are not
+supported here.  The main issue with these calls is that reading or writing
+such GPIO values can't be done from IRQ handlers.  Reading from an I2C chip
+involves sleeping to get to the head of a message queue (other chips on the
+bus may be using the controller already) and then get the response data;
+writing similarly involves sleeping.  A secondary issue is how to address
+GPIOs on those chips; globally assigned unsigned integers are not good
+choices, better ones would look like "GPIO 7 on that chip".  Managing the
+IRQs issued by such GPIOs is similarly troublesome.
+
+This API is purely for kernel space, but a userspace API could be built on
+top of it.
+
Index: osk/include/asm-arm/gpio.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ osk/include/asm-arm/gpio.h	2006-11-11 14:52:18.000000000 -0800
@@ -0,0 +1,7 @@
+#ifndef _ARCH_ARM_GPIO_H
+#define _ARCH_ARM_GPIO_H
+
+/* not all ARM platforms necessarily support this API ... */
+#include <asm/arch/gpio.h>
+
+#endif /* _ARCH_ARM_GPIO_H */
Index: osk/include/asm-arm/arch-omap/gpio.h
===================================================================
--- osk.orig/include/asm-arm/arch-omap/gpio.h	2006-11-11 14:52:16.000000000 -0800
+++ osk/include/asm-arm/arch-omap/gpio.h	2006-11-11 14:52:18.000000000 -0800
@@ -76,4 +76,58 @@ extern void omap_set_gpio_direction(int 
 extern void omap_set_gpio_dataout(int gpio, int enable);
 extern int omap_get_gpio_datain(int gpio);
 
+/*-------------------------------------------------------------------------*/
+
+/* wrappers for "new style" GPIO calls. the old OMAP-specfic ones should
+ * eventually be removed (along with this errno.h inclusion), and maybe
+ * gpios should put MPUIOs last too.
+ */
+
+#include <asm/errno.h>
+
+static inline int __must_check gpio_request(unsigned gpio, const char *label)
+	{ return omap_request_gpio(gpio); }
+
+static inline void gpio_free(unsigned gpio)
+	{ omap_free_gpio(gpio); }
+
+
+static inline int __must_check
+__gpio_set_direction(unsigned gpio, int is_input)
+{
+	if (cpu_class_is_omap2()) {
+		if (gpio > OMAP_MAX_GPIO_LINES)
+			return -EINVAL;
+	} else {
+		if (gpio > (OMAP_MAX_GPIO_LINES + 16 /* MPUIO */))
+			return -EINVAL;
+	}
+	omap_set_gpio_direction(gpio, is_input);
+	return 0;
+}
+
+static inline int gpio_direction_input(unsigned gpio)
+	{ return __gpio_set_direction(gpio, 1); }
+
+static inline int gpio_direction_output(unsigned gpio)
+	{ return __gpio_set_direction(gpio, 0); }
+
+
+static inline int gpio_get_value(unsigned gpio)
+	{ return omap_get_gpio_datain(gpio); }
+
+static inline void gpio_set_value(unsigned gpio, int value)
+	{ omap_set_gpio_dataout(gpio, value); }
+
+
+static inline int gpio_to_irq(unsigned gpio)
+	{ return OMAP_GPIO_IRQ(gpio); }
+
+static inline int irq_to_gpio(unsigned irq)
+{
+	if (cpu_class_is_omap1() && (irq < (IH_MPUIO_BASE + 16)))
+		return (irq - IH_MPUIO_BASE) + OMAP_MAX_GPIO_LINES;
+	return irq - IH_GPIO_BASE;
+}
+
 #endif

^ permalink raw reply	[flat|nested] 103+ messages in thread

end of thread, other threads:[~2007-01-02 14:19 UTC | newest]

Thread overview: 103+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-11-11 23:41 [patch/rfc 2.6.19-rc5] arch-neutral GPIO calls David Brownell
2006-11-12  1:27 ` H. Peter Anvin
2006-11-12  3:04   ` David Brownell
2006-11-12  3:15     ` H. Peter Anvin
2006-11-13  3:30 ` Bill Gatliff
2006-11-13 17:38 ` Paul Mundt
2006-11-13 17:56   ` Thiago Galesi
2006-11-13 19:25     ` David Brownell
2006-11-13 19:50       ` Bill Gatliff
2006-11-13 18:19   ` Bill Gatliff
2006-11-13 18:38     ` Paul Mundt
2006-11-13 19:29       ` Bill Gatliff
2006-11-13 20:15         ` Paul Mundt
2006-11-20 21:49           ` David Brownell
2006-11-21  3:44             ` Bill Gatliff
2006-11-21  4:45               ` David Brownell
2006-11-21  5:09                 ` Bill Gatliff
2006-11-21  5:35                   ` David Brownell
2006-11-21  6:09                     ` Paul Mundt
2006-11-21 18:13                       ` David Brownell
2006-11-22  3:36                         ` Bill Gatliff
2006-11-22  3:55                           ` Paul Mundt
2006-11-22  4:45                           ` [Bulk] " David Brownell
2006-11-22  4:47                             ` Bill Gatliff
2006-11-21 15:57                     ` Bill Gatliff
2006-11-23  0:40                       ` David Brownell
2006-11-30  6:57                         ` pHilipp Zabel
2006-11-30  7:29                           ` pHilipp Zabel
2006-11-30 22:24                           ` David Brownell
2006-11-20 22:15           ` David Brownell
2006-11-21  2:56             ` Bill Gatliff
2006-11-13 20:00       ` David Brownell
2006-11-13 21:30         ` Paul Mundt
2006-11-14  3:21           ` David Brownell
2006-11-13 19:21   ` David Brownell
2006-11-13 19:43     ` Bill Gatliff
2006-11-13 20:15       ` David Brownell
2006-11-13 20:26         ` Bill Gatliff
2006-11-13 20:53           ` David Brownell
2006-11-13 20:58             ` Bill Gatliff
2006-11-13 20:29         ` Bill Gatliff
2006-11-16 14:54 ` [RFC/PATCH] arch-neutral GPIO calls: AVR32 implementation Haavard Skinnemoen
2006-11-20 21:47   ` David Brownell
2006-11-21  3:11     ` Bill Gatliff
2006-11-21  5:06       ` David Brownell
2006-11-21  5:51         ` Bill Gatliff
2006-11-21 18:19           ` David Brownell
2006-11-21  9:11     ` Haavard Skinnemoen
2006-11-21 19:03       ` David Brownell
2006-11-28 12:36         ` [RFC/PATCH] arch-neutral GPIO calls: AVR32 implementation [take 2] Haavard Skinnemoen
2006-11-30 19:05           ` David Brownell
2006-12-01  9:51             ` Haavard Skinnemoen
2006-12-20 21:04 ` [patch 2.6.20-rc1 0/6] arch-neutral GPIO calls David Brownell
2006-12-20 21:08   ` [patch 2.6.20-rc1 1/6] GPIO core David Brownell
2006-12-27 17:49     ` Pavel Machek
2006-12-28 22:05       ` David Brownell
2006-12-29  0:27         ` Pavel Machek
2006-12-30  1:18           ` David Brownell
2007-01-01 20:55             ` Pavel Machek
2007-01-01 21:27               ` David Brownell
2007-01-02 14:18                 ` Pavel Machek
2006-12-20 21:09   ` [patch 2.6.20-rc1 2/6] OMAP GPIO wrappers David Brownell
2006-12-20 21:11   ` [patch 2.6.20-rc1 3/6] AT91 " David Brownell
2006-12-21  6:10     ` Andrew Morton
2006-12-21  6:45       ` David Brownell
2006-12-20 21:12   ` [patch 2.6.20-rc1 4/6] PXA " David Brownell
2006-12-21  6:12     ` Andrew Morton
2006-12-21  6:44       ` David Brownell
2006-12-21 14:27         ` Nicolas Pitre
2006-12-21 15:03           ` pHilipp Zabel
2006-12-21 17:25             ` Nicolas Pitre
2006-12-21 19:32               ` pHilipp Zabel
2006-12-21 20:10                 ` Nicolas Pitre
2006-12-21 20:32                   ` Bill Gatliff
2006-12-22  6:53                   ` pHilipp Zabel
2006-12-28 20:47                     ` David Brownell
2006-12-30  2:15                       ` Nicolas Pitre
2006-12-30  2:38                         ` David Brownell
2007-01-01 19:43                         ` David Brownell
2006-12-30  1:13                     ` David Brownell
2006-12-21 19:25             ` David Brownell
2006-12-27 17:53     ` Pavel Machek
2006-12-28 20:48       ` David Brownell
2006-12-28 20:50         ` Pavel Machek
2006-12-28 20:53           ` Pavel Machek
2006-12-20 21:13   ` [patch 2.6.20-rc1 5/6] SA1100 " David Brownell
2006-12-21  6:13     ` Andrew Morton
2006-12-22  7:16       ` pHilipp Zabel
2006-12-22 15:05         ` Nicolas Pitre
2006-12-30  2:21         ` David Brownell
2006-12-30  3:15           ` Nicolas Pitre
2006-12-30  6:01             ` David Brownell
2006-12-30 13:59               ` pHilipp Zabel
2006-12-30 15:08                 ` Russell King
2006-12-23 11:37     ` Russell King
2006-12-23 20:39       ` David Brownell
2006-12-27 18:24     ` Pavel Machek
2006-12-20 21:14   ` [patch 2.6.20-rc1 6/6] S3C2410 " David Brownell
2006-12-21 10:33     ` Arnaud Patard
2006-12-21 15:29       ` pHilipp Zabel
2006-12-23 11:40       ` Russell King
2006-12-20 23:30   ` [patch 2.6.20-rc1 0/6] arch-neutral GPIO calls Håvard Skinnemoen
2006-12-20 23:46     ` David Brownell

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.