All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: [patch 2.6.20-rc1 0/6] arch-neutral GPIO calls
@ 2006-12-31 19:11 Kevin O'Connor
  2007-01-01 20:06 ` David Brownell
  0 siblings, 1 reply; 6+ messages in thread
From: Kevin O'Connor @ 2006-12-31 19:11 UTC (permalink / raw)
  To: david-b; +Cc: linux-kernel

> Based on earlier discussion, I'm sending a refresh of the generic GPIO
> patch, with several (ARM based) implementations in separate patches:

Hi Dave,

I'm very interested in seeing an abstraction for gpios.  Over the last
several months, I've been working on getting Linux running on my phone
- see www.handhelds.org for more information.  These types of ARM
based PDAs and phones are riddled with GPIOs, and there is frequent
code duplication when two machines have to do similar functionality
with different gpios.

Unfortunately, I fear the implementation you propose is not robust
enough to handle the cases I need to handle.  In particular, I think a
"struct gpio" instead of "int gpio" is needed to describe a gpio pin.

Some background - on the phone I use, it has the standard PXA27x
gpios, a gpio extender chip (egpio) which is connected via the memory
bus, and a micro-controller attached via an i2c like bus.  Other
phones will commonly have the PXA27x, "egpio", and an "asic3" chip.
With the sale of the PXA line, it seems Samsung and TI based ARM chips
(and their corresponding GPIOs) will be on the rise.

As you know, basic functionality like setting a LED, detecting a
button press, requesting an irq, etc. are common with GPIOs regardless
of which platform, or which gpio chip, is in use.

The concern I have with your current implementation is that I don't
see a way to flexibly add in support for additional gpio pins on a
machine by machine basis.  The code does do a good job of abstracting
gpios based on the primary architecture (eg, PXA vs OMAP), but not on
a chip basis (eg, PXA vs ASIC3).

Specifically, once the code pulls in "<asm/gpio.h>" it will get the
PXA gpio code, but this will only allow access to the arch gpios, not
the machine specific gpios.  Also, one of the goals of the developers
at handhelds.org is to have one kernel for many different phones --
from a userspace point of view they don't generally differ very much.
As such, this isn't a matter of just having each "machine" override
the gpio.h file at compile time; it really needs to be done at
runtime.

I understand that the existing code works entirely on integers.
However, I fear this is at attribute of the problem, not of the
solution.

> - Core patch, doc + <asm-arm/gpio.h> + <asm-generic/gpio.h>
> - OMAP implementation
> - AT91 implementation
> - PXA implementation
> - SA1100 implementation
> - S3C2410 implementation

Your patch clearly shows that the existing implementations are using
integers.  I think there is a simple way to reuse the existing
implementations.  For example on pxa one could do something like:

============= include/linux/gpio.h

struct gpio_ops {
        int (*gpio_direction_input)(struct *gpio);
        ...
};

struct gpio {
     struct gpio_ops *ops;
};

============= arch/arm/mach-pxa/gpio.c

struct gpio pxa_gpios[120] = {
        {.ops = pxa_gpio_ops}, ...
};

int pxa_gpio_direction_input(struct *gpio) {
        int pxa_gpio = gpio - pxa_gpios;
        pxa_gpio_mode(pxa_gpio | GPIO_IN);
        return 0;
}

...

> Other than clarifications, the main change in the doc is defining
> new calls safe for use with GPIOs on things like pcf8574 I2C gpio
> expanders; those new calls can sleep, but are otherwise the same as
> the spinlock-safe versions. The implementations above implement that
> as a wrapper (the asm-generic header) around the spinlock-safe calls.

As above, I'm confused how these expanders would work in practice.
The expanders would be present on a machine by machine basis but the
code seems to be implemented on an arch by arch basis.  Perhaps an
example would help me.

Please CC me on replies.

Cheers,
-Kevin

^ permalink raw reply	[flat|nested] 6+ messages in thread
* [patch/rfc 2.6.19-rc5] arch-neutral GPIO calls
@ 2006-11-11 23:41 David Brownell
  2006-12-20 21:04 ` [patch 2.6.20-rc1 0/6] " David Brownell
  0 siblings, 1 reply; 6+ 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] 6+ messages in thread

end of thread, other threads:[~2007-01-01 23:17 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-12-31 19:11 [patch 2.6.20-rc1 0/6] arch-neutral GPIO calls Kevin O'Connor
2007-01-01 20:06 ` David Brownell
2007-01-01 23:17   ` Kevin O'Connor
  -- strict thread matches above, loose matches on Subject: below --
2006-11-11 23:41 [patch/rfc 2.6.19-rc5] " David Brownell
2006-12-20 21:04 ` [patch 2.6.20-rc1 0/6] " David Brownell
2006-12-20 23:30   ` 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.