All pastes #269651 Raw Edit

Diff

public text v1 · immutable
·published 2006-12-06 19:02 UTC
rendered paste body
                                                                                                                                                                                                                                                               X-Gmail-Received: 8764e07bac7a1111a242ba0c361a4ca3bda06744Delivered-To: philipp.zabel@gmail.comReceived: by 10.78.175.4 with SMTP id x4cs353232hue;        Sat, 11 Nov 2006 15:46:45 -0800 (PST)Received: by 10.35.46.6 with SMTP id y6mr6889097pyj.1163288804754;        Sat, 11 Nov 2006 15:46:44 -0800 (PST)Return-Path: <linux-kernel-owner@vger.kernel.org>Received: from vger.kernel.org (vger.kernel.org [209.132.176.167])        by mx.google.com with ESMTP id f51si3942061pyh.2006.11.11.15.46.28;        Sat, 11 Nov 2006 15:46:44 -0800 (PST)Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.176.167 as permitted sender)DomainKey-Status: bad (test mode)Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand	id S1754907AbWKKXll (ORCPT <rfc822;bortas@gmail.com> + 99 others);	Sat, 11 Nov 2006 18:41:41 -0500Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1754908AbWKKXll	(ORCPT <rfc822;linux-kernel-outgoing>);	Sat, 11 Nov 2006 18:41:41 -0500Received: from smtp113.sbc.mail.mud.yahoo.com ([68.142.198.212]:40327 "HELO	smtp113.sbc.mail.mud.yahoo.com") by vger.kernel.org with SMTP	id S1754906AbWKKXlk (ORCPT <rfc822;linux-kernel@vger.kernel.org>);	Sat, 11 Nov 2006 18:41:40 -0500Received: (qmail 20056 invoked from network); 11 Nov 2006 23:41:39 -0000DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws;  s=s1024; d=pacbell.net;  h=Received:X-YMail-OSG:From:To:Subject:Date:User-Agent:Cc:MIME-Version:Content-Type:Content-Transfer-Encoding:Content-Disposition:Message-Id;  b=IaKVVvLMO4mnbhOedwCyDfTJ8fPlfmgZqnbc+iW29LkPr5bSCNfpe3mz0e95pm3NmveQLlIQbMBvbbGz+uzbSbPu71xfw1521zeG9hWZAtJzwroeLVIG7M3iQL6zL3rlZMSh5oPrh79qFdLsMHeCzbtk4dWwtVctFkTN+TqTdIY=  ;Received: from unknown (HELO ascent) (david-b@pacbell.net@69.226.224.97 with plain)  by smtp113.sbc.mail.mud.yahoo.com with SMTP; 11 Nov 2006 23:41:38 -0000X-YMail-OSG: 9uD__rYVM1nPyN47LqPW3.Y2rsPS4IEsbwkdVomsmn2n5uwcs4ytJe5dS5.5OrCSgVlgbE1UZU_iDJLEM.vh1eq_oiLCoWt8gq8EhtubtPvdI_TJU5zB1LSjWJMXEQgGU75edtLQltdMHpN3EetL5tAb9Wu0XSKSpss-From:	David Brownell <david-b@pacbell.net>To:	Linux Kernel list <linux-kernel@vger.kernel.org>Subject: [patch/rfc 2.6.19-rc5] arch-neutral GPIO callsDate:	Sat, 11 Nov 2006 15:41:32 -0800User-Agent: KMail/1.7.1Cc:	Andrew Morton <akpm@osdl.org>,	Andrew Victor <andrew@sanpeople.com>,	Bill Gatliff <bgat@billgatliff.com>,	Haavard Skinnemoen <hskinnemoen@atmel.com>, jamey.hicks@hp.com,	Kevin Hilman <khilman@mvista.com>,	Nicolas Pitre <nico@cam.org>,	Russell King <rmk@arm.linux.org.uk>,	Tony Lindgren <tony@atomide.com>MIME-Version: 1.0Content-Type: text/plain;  charset="us-ascii"Content-Transfer-Encoding: 7bitContent-Disposition: inlineMessage-Id: <200611111541.34699.david-b@pacbell.net>Sender:	linux-kernel-owner@vger.kernel.orgPrecedence: bulkX-Mailing-List:	linux-kernel@vger.kernel.orgI 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=2Below, find what I think is a useful proposal, trivially implementable onmany ARMs (at91, omap, pxa, ep93xx, ixp2000, pnx4008, davinci, more) as wellas 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.txtComments?- Dave============================	CUT HEREThis defines a simple and minimalist convention for GPIO APIs, and animplementation 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 callsThe immediate need for such a cross-architecture API convention is to supportdrivers that work the same on AT91 ARM and AVR32 AP7000 chips, which embed manyof 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-To unsubscribe from this list: send the line "unsubscribe linux-kernel" inthe body of a message to majordomo@vger.kernel.orgMore majordomo info at  http://vger.kernel.org/majordomo-info.htmlPlease read the FAQ at  http://www.tux.org/lkml/