diff options
Diffstat (limited to 'packages/kexecboot/linux-kexecboot-2.6.24/tosa/0022-Provide-new-implementation-infrastructure-that-platf.patch')
-rw-r--r-- | packages/kexecboot/linux-kexecboot-2.6.24/tosa/0022-Provide-new-implementation-infrastructure-that-platf.patch | 746 |
1 files changed, 0 insertions, 746 deletions
diff --git a/packages/kexecboot/linux-kexecboot-2.6.24/tosa/0022-Provide-new-implementation-infrastructure-that-platf.patch b/packages/kexecboot/linux-kexecboot-2.6.24/tosa/0022-Provide-new-implementation-infrastructure-that-platf.patch deleted file mode 100644 index f39fedbbaa..0000000000 --- a/packages/kexecboot/linux-kexecboot-2.6.24/tosa/0022-Provide-new-implementation-infrastructure-that-platf.patch +++ /dev/null @@ -1,746 +0,0 @@ -From 3a0251c01446f3a6763e4406ca5495102db63aa4 Mon Sep 17 00:00:00 2001 -From: David Brownell <dbrownell@users.sourceforge.net> -Date: Fri, 18 Jan 2008 00:35:20 +0300 -Subject: [PATCH 22/64] Provide new implementation infrastructure that platforms may choose to use - when implementing the GPIO programming interface. Platforms can update their - GPIO support to use this. In many cases the incremental cost to access a - non-inlined GPIO should be less than a dozen instructions, with the memory - cost being about a page (total) of extra data and code. The upside is: - - * Providing two features which were "want to have (but OK to defer)" when - GPIO interfaces were first discussed in November 2006: - - - A "struct gpio_chip" to plug in GPIOs that aren't directly supported - by SOC platforms, but come from FPGAs or other multifunction devices - using conventional device registers (like UCB-1x00 or SM501 GPIOs, - and southbridges in PCs with more open specs than usual). - - - Full support for message-based GPIO expanders, where registers are - accessed through sleeping I/O calls. Previous support for these - "cansleep" calls was just stubs. (One example: the widely used - pcf8574 I2C chips, with 8 GPIOs each.) - - * Including a non-stub implementation of the gpio_{request,free}() calls, - making those calls much more useful. The diagnostic labels are also - recorded given DEBUG_FS, so /sys/kernel/debug/gpio can show a snapshot - of all GPIOs known to this infrastructure. - -The driver programming interfaces introduced in 2.6.21 do not change at all; -this infrastructure is entirely below those covers. - -Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> -Cc: Sam Ravnborg <sam@ravnborg.org> -Cc: Jean Delvare <khali@linux-fr.org> -Cc: Eric Miao <eric.miao@marvell.com> -Cc: Haavard Skinnemoen <hskinnemoen@atmel.com> -Cc: Philipp Zabel <philipp.zabel@gmail.com> -Cc: Russell King <rmk@arm.linux.org.uk> -Cc: Ben Gardner <bgardner@wabtec.com> -Signed-off-by: Andrew Morton <akpm@linux-foundation.org> ---- - drivers/gpio/Makefile | 2 + - drivers/gpio/gpiolib.c | 567 ++++++++++++++++++++++++++++++++++++++++++++ - include/asm-generic/gpio.h | 98 ++++++++ - 3 files changed, 667 insertions(+), 0 deletions(-) - create mode 100644 drivers/gpio/gpiolib.c - -diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile -index cdbba6b..2db28ce 100644 ---- a/drivers/gpio/Makefile -+++ b/drivers/gpio/Makefile -@@ -1,3 +1,5 @@ - # gpio support: dedicated expander chips, etc - - ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG -+ -+obj-$(CONFIG_HAVE_GPIO_LIB) += gpiolib.o -diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c -new file mode 100644 -index 0000000..d8db2f8 ---- /dev/null -+++ b/drivers/gpio/gpiolib.c -@@ -0,0 +1,567 @@ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/irq.h> -+#include <linux/spinlock.h> -+ -+#include <asm/gpio.h> -+ -+ -+/* Optional implementation infrastructure for GPIO interfaces. -+ * -+ * Platforms may want to use this if they tend to use very many GPIOs -+ * that aren't part of a System-On-Chip core; or across I2C/SPI/etc. -+ * -+ * When kernel footprint or instruction count is an issue, simpler -+ * implementations may be preferred. The GPIO programming interface -+ * allows for inlining speed-critical get/set operations for common -+ * cases, so that access to SOC-integrated GPIOs can sometimes cost -+ * only an instruction or two per bit. -+ */ -+ -+ -+/* When debugging, extend minimal trust to callers and platform code. -+ * Also emit diagnostic messages that may help initial bringup, when -+ * board setup or driver bugs are most common. -+ * -+ * Otherwise, minimize overhead in what may be bitbanging codepaths. -+ */ -+#ifdef DEBUG -+#define extra_checks 1 -+#else -+#define extra_checks 0 -+#endif -+ -+/* gpio_lock prevents conflicts during gpio_desc[] table updates. -+ * While any GPIO is requested, its gpio_chip is not removable; -+ * each GPIO's "requested" flag serves as a lock and refcount. -+ */ -+static DEFINE_SPINLOCK(gpio_lock); -+ -+struct gpio_desc { -+ struct gpio_chip *chip; -+ unsigned long flags; -+/* flag symbols are bit numbers */ -+#define FLAG_REQUESTED 0 -+#define FLAG_IS_OUT 1 -+ -+#ifdef CONFIG_DEBUG_FS -+ const char *label; -+#endif -+}; -+static struct gpio_desc gpio_desc[ARCH_NR_GPIOS]; -+ -+static inline void desc_set_label(struct gpio_desc *d, const char *label) -+{ -+#ifdef CONFIG_DEBUG_FS -+ d->label = label; -+#endif -+} -+ -+/* Warn when drivers omit gpio_request() calls -- legal but ill-advised -+ * when setting direction, and otherwise illegal. Until board setup code -+ * and drivers use explicit requests everywhere (which won't happen when -+ * those calls have no teeth) we can't avoid autorequesting. This nag -+ * message should motivate switching to explicit requests... -+ */ -+static void gpio_ensure_requested(struct gpio_desc *desc) -+{ -+ if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) { -+ pr_warning("GPIO-%d autorequested\n", (int)(desc - gpio_desc)); -+ desc_set_label(desc, "[auto]"); -+ } -+} -+ -+/* caller holds gpio_lock *OR* gpio is marked as requested */ -+static inline struct gpio_chip *gpio_to_chip(unsigned gpio) -+{ -+ return gpio_desc[gpio].chip; -+} -+ -+/** -+ * gpiochip_add() - register a gpio_chip -+ * @chip: the chip to register, with chip->base initialized -+ * Context: potentially before irqs or kmalloc will work -+ * -+ * Returns a negative errno if the chip can't be registered, such as -+ * because the chip->base is invalid or already associated with a -+ * different chip. Otherwise it returns zero as a success code. -+ */ -+int gpiochip_add(struct gpio_chip *chip) -+{ -+ unsigned long flags; -+ int status = 0; -+ unsigned id; -+ -+ /* NOTE chip->base negative is reserved to mean a request for -+ * dynamic allocation. We don't currently support that. -+ */ -+ -+ if (chip->base < 0 || (chip->base + chip->ngpio) >= ARCH_NR_GPIOS) { -+ status = -EINVAL; -+ goto fail; -+ } -+ -+ spin_lock_irqsave(&gpio_lock, flags); -+ -+ /* these GPIO numbers must not be managed by another gpio_chip */ -+ for (id = chip->base; id < chip->base + chip->ngpio; id++) { -+ if (gpio_desc[id].chip != NULL) { -+ status = -EBUSY; -+ break; -+ } -+ } -+ if (status == 0) { -+ for (id = chip->base; id < chip->base + chip->ngpio; id++) { -+ gpio_desc[id].chip = chip; -+ gpio_desc[id].flags = 0; -+ } -+ } -+ -+ spin_unlock_irqrestore(&gpio_lock, flags); -+fail: -+ /* failures here can mean systems won't boot... */ -+ if (status) -+ pr_err("gpiochip_add: gpios %d..%d (%s) not registered\n", -+ chip->base, chip->base + chip->ngpio, -+ chip->label ? : "generic"); -+ return status; -+} -+EXPORT_SYMBOL_GPL(gpiochip_add); -+ -+/** -+ * gpiochip_remove() - unregister a gpio_chip -+ * @chip: the chip to unregister -+ * -+ * A gpio_chip with any GPIOs still requested may not be removed. -+ */ -+int gpiochip_remove(struct gpio_chip *chip) -+{ -+ unsigned long flags; -+ int status = 0; -+ unsigned id; -+ -+ spin_lock_irqsave(&gpio_lock, flags); -+ -+ for (id = chip->base; id < chip->base + chip->ngpio; id++) { -+ if (test_bit(FLAG_REQUESTED, &gpio_desc[id].flags)) { -+ status = -EBUSY; -+ break; -+ } -+ } -+ if (status == 0) { -+ for (id = chip->base; id < chip->base + chip->ngpio; id++) -+ gpio_desc[id].chip = NULL; -+ } -+ -+ spin_unlock_irqrestore(&gpio_lock, flags); -+ return status; -+} -+EXPORT_SYMBOL_GPL(gpiochip_remove); -+ -+ -+/* These "optional" allocation calls help prevent drivers from stomping -+ * on each other, and help provide better diagnostics in debugfs. -+ * They're called even less than the "set direction" calls. -+ */ -+int gpio_request(unsigned gpio, const char *label) -+{ -+ struct gpio_desc *desc; -+ int status = -EINVAL; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&gpio_lock, flags); -+ -+ if (gpio >= ARCH_NR_GPIOS) -+ goto done; -+ desc = &gpio_desc[gpio]; -+ if (desc->chip == NULL) -+ goto done; -+ -+ /* NOTE: gpio_request() can be called in early boot, -+ * before IRQs are enabled. -+ */ -+ -+ if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) { -+ desc_set_label(desc, label ? : "?"); -+ status = 0; -+ } else -+ status = -EBUSY; -+ -+done: -+ if (status) -+ pr_debug("gpio_request: gpio-%d (%s) status %d\n", -+ gpio, label ? : "?", status); -+ spin_unlock_irqrestore(&gpio_lock, flags); -+ return status; -+} -+EXPORT_SYMBOL_GPL(gpio_request); -+ -+void gpio_free(unsigned gpio) -+{ -+ unsigned long flags; -+ struct gpio_desc *desc; -+ -+ if (gpio >= ARCH_NR_GPIOS) { -+ WARN_ON(extra_checks); -+ return; -+ } -+ -+ spin_lock_irqsave(&gpio_lock, flags); -+ -+ desc = &gpio_desc[gpio]; -+ if (desc->chip && test_and_clear_bit(FLAG_REQUESTED, &desc->flags)) -+ desc_set_label(desc, NULL); -+ else -+ WARN_ON(extra_checks); -+ -+ spin_unlock_irqrestore(&gpio_lock, flags); -+} -+EXPORT_SYMBOL_GPL(gpio_free); -+ -+ -+/** -+ * gpiochip_is_requested - return string iff signal was requested -+ * @chip: controller managing the signal -+ * @offset: of signal within controller's 0..(ngpio - 1) range -+ * -+ * Returns NULL if the GPIO is not currently requested, else a string. -+ * If debugfs support is enabled, the string returned is the label passed -+ * to gpio_request(); otherwise it is a meaningless constant. -+ * -+ * This function is for use by GPIO controller drivers. The label can -+ * help with diagnostics, and knowing that the signal is used as a GPIO -+ * can help avoid accidentally multiplexing it to another controller. -+ */ -+const char *gpiochip_is_requested(struct gpio_chip *chip, unsigned offset) -+{ -+ unsigned gpio = chip->base + offset; -+ -+ if (gpio >= ARCH_NR_GPIOS || gpio_desc[gpio].chip != chip) -+ return NULL; -+ if (test_bit(FLAG_REQUESTED, &gpio_desc[gpio].flags) == 0) -+ return NULL; -+#ifdef CONFIG_DEBUG_FS -+ return gpio_desc[gpio].label; -+#else -+ return "?"; -+#endif -+} -+EXPORT_SYMBOL_GPL(gpiochip_is_requested); -+ -+ -+/* Drivers MUST set GPIO direction before making get/set calls. In -+ * some cases this is done in early boot, before IRQs are enabled. -+ * -+ * As a rule these aren't called more than once (except for drivers -+ * using the open-drain emulation idiom) so these are natural places -+ * to accumulate extra debugging checks. Note that we can't (yet) -+ * rely on gpio_request() having been called beforehand. -+ */ -+ -+int gpio_direction_input(unsigned gpio) -+{ -+ unsigned long flags; -+ struct gpio_chip *chip; -+ struct gpio_desc *desc = &gpio_desc[gpio]; -+ int status = -EINVAL; -+ -+ spin_lock_irqsave(&gpio_lock, flags); -+ -+ if (gpio >= ARCH_NR_GPIOS) -+ goto fail; -+ chip = desc->chip; -+ if (!chip || !chip->get || !chip->direction_input) -+ goto fail; -+ gpio -= chip->base; -+ if (gpio >= chip->ngpio) -+ goto fail; -+ gpio_ensure_requested(desc); -+ -+ /* now we know the gpio is valid and chip won't vanish */ -+ -+ spin_unlock_irqrestore(&gpio_lock, flags); -+ -+ might_sleep_if(extra_checks && chip->can_sleep); -+ -+ status = chip->direction_input(chip, gpio); -+ if (status == 0) -+ clear_bit(FLAG_IS_OUT, &desc->flags); -+ return status; -+fail: -+ spin_unlock_irqrestore(&gpio_lock, flags); -+ if (status) -+ pr_debug("%s: gpio-%d status %d\n", -+ __FUNCTION__, gpio, status); -+ return status; -+} -+EXPORT_SYMBOL_GPL(gpio_direction_input); -+ -+int gpio_direction_output(unsigned gpio, int value) -+{ -+ unsigned long flags; -+ struct gpio_chip *chip; -+ struct gpio_desc *desc = &gpio_desc[gpio]; -+ int status = -EINVAL; -+ -+ spin_lock_irqsave(&gpio_lock, flags); -+ -+ if (gpio >= ARCH_NR_GPIOS) -+ goto fail; -+ chip = desc->chip; -+ if (!chip || !chip->set || !chip->direction_output) -+ goto fail; -+ gpio -= chip->base; -+ if (gpio >= chip->ngpio) -+ goto fail; -+ gpio_ensure_requested(desc); -+ -+ /* now we know the gpio is valid and chip won't vanish */ -+ -+ spin_unlock_irqrestore(&gpio_lock, flags); -+ -+ might_sleep_if(extra_checks && chip->can_sleep); -+ -+ status = chip->direction_output(chip, gpio, value); -+ if (status == 0) -+ set_bit(FLAG_IS_OUT, &desc->flags); -+ return status; -+fail: -+ spin_unlock_irqrestore(&gpio_lock, flags); -+ if (status) -+ pr_debug("%s: gpio-%d status %d\n", -+ __FUNCTION__, gpio, status); -+ return status; -+} -+EXPORT_SYMBOL_GPL(gpio_direction_output); -+ -+ -+/* I/O calls are only valid after configuration completed; the relevant -+ * "is this a valid GPIO" error checks should already have been done. -+ * -+ * "Get" operations are often inlinable as reading a pin value register, -+ * and masking the relevant bit in that register. -+ * -+ * When "set" operations are inlinable, they involve writing that mask to -+ * one register to set a low value, or a different register to set it high. -+ * Otherwise locking is needed, so there may be little value to inlining. -+ * -+ *------------------------------------------------------------------------ -+ * -+ * IMPORTANT!!! The hot paths -- get/set value -- assume that callers -+ * have requested the GPIO. That can include implicit requesting by -+ * a direction setting call. Marking a gpio as requested locks its chip -+ * in memory, guaranteeing that these table lookups need no more locking -+ * and that gpiochip_remove() will fail. -+ * -+ * REVISIT when debugging, consider adding some instrumentation to ensure -+ * that the GPIO was actually requested. -+ */ -+ -+/** -+ * __gpio_get_value() - return a gpio's value -+ * @gpio: gpio whose value will be returned -+ * Context: any -+ * -+ * This is used directly or indirectly to implement gpio_get_value(). -+ * It returns the zero or nonzero value provided by the associated -+ * gpio_chip.get() method; or zero if no such method is provided. -+ */ -+int __gpio_get_value(unsigned gpio) -+{ -+ struct gpio_chip *chip; -+ -+ chip = gpio_to_chip(gpio); -+ WARN_ON(extra_checks && chip->can_sleep); -+ return chip->get ? chip->get(chip, gpio - chip->base) : 0; -+} -+EXPORT_SYMBOL_GPL(__gpio_get_value); -+ -+/** -+ * __gpio_set_value() - assign a gpio's value -+ * @gpio: gpio whose value will be assigned -+ * @value: value to assign -+ * Context: any -+ * -+ * This is used directly or indirectly to implement gpio_set_value(). -+ * It invokes the associated gpio_chip.set() method. -+ */ -+void __gpio_set_value(unsigned gpio, int value) -+{ -+ struct gpio_chip *chip; -+ -+ chip = gpio_to_chip(gpio); -+ WARN_ON(extra_checks && chip->can_sleep); -+ chip->set(chip, gpio - chip->base, value); -+} -+EXPORT_SYMBOL_GPL(__gpio_set_value); -+ -+/** -+ * __gpio_cansleep() - report whether gpio value access will sleep -+ * @gpio: gpio in question -+ * Context: any -+ * -+ * This is used directly or indirectly to implement gpio_cansleep(). It -+ * returns nonzero if access reading or writing the GPIO value can sleep. -+ */ -+int __gpio_cansleep(unsigned gpio) -+{ -+ struct gpio_chip *chip; -+ -+ /* only call this on GPIOs that are valid! */ -+ chip = gpio_to_chip(gpio); -+ -+ return chip->can_sleep; -+} -+EXPORT_SYMBOL_GPL(__gpio_cansleep); -+ -+ -+ -+/* There's no value in making it easy to inline GPIO calls that may sleep. -+ * Common examples include ones connected to I2C or SPI chips. -+ */ -+ -+int gpio_get_value_cansleep(unsigned gpio) -+{ -+ struct gpio_chip *chip; -+ -+ might_sleep_if(extra_checks); -+ chip = gpio_to_chip(gpio); -+ return chip->get(chip, gpio - chip->base); -+} -+EXPORT_SYMBOL_GPL(gpio_get_value_cansleep); -+ -+void gpio_set_value_cansleep(unsigned gpio, int value) -+{ -+ struct gpio_chip *chip; -+ -+ might_sleep_if(extra_checks); -+ chip = gpio_to_chip(gpio); -+ chip->set(chip, gpio - chip->base, value); -+} -+EXPORT_SYMBOL_GPL(gpio_set_value_cansleep); -+ -+ -+#ifdef CONFIG_DEBUG_FS -+ -+#include <linux/debugfs.h> -+#include <linux/seq_file.h> -+ -+ -+static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip) -+{ -+ unsigned i; -+ unsigned gpio = chip->base; -+ struct gpio_desc *gdesc = &gpio_desc[gpio]; -+ int is_out; -+ -+ for (i = 0; i < chip->ngpio; i++, gpio++, gdesc++) { -+ if (!test_bit(FLAG_REQUESTED, &gdesc->flags)) -+ continue; -+ -+ is_out = test_bit(FLAG_IS_OUT, &gdesc->flags); -+ seq_printf(s, " gpio-%-3d (%-12s) %s %s", -+ gpio, gdesc->label, -+ is_out ? "out" : "in ", -+ chip->get -+ ? (chip->get(chip, i) ? "hi" : "lo") -+ : "? "); -+ -+ if (!is_out) { -+ int irq = gpio_to_irq(gpio); -+ struct irq_desc *desc = irq_desc + irq; -+ -+ /* This races with request_irq(), set_irq_type(), -+ * and set_irq_wake() ... but those are "rare". -+ * -+ * More significantly, trigger type flags aren't -+ * currently maintained by genirq. -+ */ -+ if (irq >= 0 && desc->action) { -+ char *trigger; -+ -+ switch (desc->status & IRQ_TYPE_SENSE_MASK) { -+ case IRQ_TYPE_NONE: -+ trigger = "(default)"; -+ break; -+ case IRQ_TYPE_EDGE_FALLING: -+ trigger = "edge-falling"; -+ break; -+ case IRQ_TYPE_EDGE_RISING: -+ trigger = "edge-rising"; -+ break; -+ case IRQ_TYPE_EDGE_BOTH: -+ trigger = "edge-both"; -+ break; -+ case IRQ_TYPE_LEVEL_HIGH: -+ trigger = "level-high"; -+ break; -+ case IRQ_TYPE_LEVEL_LOW: -+ trigger = "level-low"; -+ break; -+ default: -+ trigger = "?trigger?"; -+ break; -+ } -+ -+ seq_printf(s, " irq-%d %s%s", -+ irq, trigger, -+ (desc->status & IRQ_WAKEUP) -+ ? " wakeup" : ""); -+ } -+ } -+ -+ seq_printf(s, "\n"); -+ } -+} -+ -+static int gpiolib_show(struct seq_file *s, void *unused) -+{ -+ struct gpio_chip *chip = NULL; -+ unsigned gpio; -+ int started = 0; -+ -+ /* REVISIT this isn't locked against gpio_chip removal ... */ -+ -+ for (gpio = 0; gpio < ARCH_NR_GPIOS; gpio++) { -+ if (chip == gpio_desc[gpio].chip) -+ continue; -+ chip = gpio_desc[gpio].chip; -+ if (!chip) -+ continue; -+ -+ seq_printf(s, "%sGPIOs %d-%d, %s%s:\n", -+ started ? "\n" : "", -+ chip->base, chip->base + chip->ngpio - 1, -+ chip->label ? : "generic", -+ chip->can_sleep ? ", can sleep" : ""); -+ started = 1; -+ if (chip->dbg_show) -+ chip->dbg_show(s, chip); -+ else -+ gpiolib_dbg_show(s, chip); -+ } -+ return 0; -+} -+ -+static int gpiolib_open(struct inode *inode, struct file *file) -+{ -+ return single_open(file, gpiolib_show, NULL); -+} -+ -+static struct file_operations gpiolib_operations = { -+ .open = gpiolib_open, -+ .read = seq_read, -+ .llseek = seq_lseek, -+ .release = single_release, -+}; -+ -+static int __init gpiolib_debugfs_init(void) -+{ -+ /* /sys/kernel/debug/gpio */ -+ (void) debugfs_create_file("gpio", S_IFREG | S_IRUGO, -+ NULL, NULL, &gpiolib_operations); -+ return 0; -+} -+subsys_initcall(gpiolib_debugfs_init); -+ -+#endif /* DEBUG_FS */ -diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h -index 2d0aab1..f29a502 100644 ---- a/include/asm-generic/gpio.h -+++ b/include/asm-generic/gpio.h -@@ -1,6 +1,102 @@ - #ifndef _ASM_GENERIC_GPIO_H - #define _ASM_GENERIC_GPIO_H - -+#ifdef CONFIG_HAVE_GPIO_LIB -+ -+/* Platforms may implement their GPIO interface with library code, -+ * at a small performance cost for non-inlined operations and some -+ * extra memory (for code and for per-GPIO table entries). -+ * -+ * While the GPIO programming interface defines valid GPIO numbers -+ * to be in the range 0..MAX_INT, this library restricts them to the -+ * smaller range 0..ARCH_NR_GPIOS. -+ */ -+ -+#ifndef ARCH_NR_GPIOS -+#define ARCH_NR_GPIOS 256 -+#endif -+ -+struct seq_file; -+ -+/** -+ * struct gpio_chip - abstract a GPIO controller -+ * @label: for diagnostics -+ * @direction_input: configures signal "offset" as input, or returns error -+ * @get: returns value for signal "offset"; for output signals this -+ * returns either the value actually sensed, or zero -+ * @direction_output: configures signal "offset" as output, or returns error -+ * @set: assigns output value for signal "offset" -+ * @dbg_show: optional routine to show contents in debugfs; default code -+ * will be used when this is omitted, but custom code can show extra -+ * state (such as pullup/pulldown configuration). -+ * @base: identifies the first GPIO number handled by this chip; or, if -+ * negative during registration, requests dynamic ID allocation. -+ * @ngpio: the number of GPIOs handled by this controller; the last GPIO -+ * handled is (base + ngpio - 1). -+ * @can_sleep: flag must be set iff get()/set() methods sleep, as they -+ * must while accessing GPIO expander chips over I2C or SPI -+ * -+ * A gpio_chip can help platforms abstract various sources of GPIOs so -+ * they can all be accessed through a common programing interface. -+ * Example sources would be SOC controllers, FPGAs, multifunction -+ * chips, dedicated GPIO expanders, and so on. -+ * -+ * Each chip controls a number of signals, identified in method calls -+ * by "offset" values in the range 0..(@ngpio - 1). When those signals -+ * are referenced through calls like gpio_get_value(gpio), the offset -+ * is calculated by subtracting @base from the gpio number. -+ */ -+struct gpio_chip { -+ char *label; -+ -+ int (*direction_input)(struct gpio_chip *chip, -+ unsigned offset); -+ int (*get)(struct gpio_chip *chip, -+ unsigned offset); -+ int (*direction_output)(struct gpio_chip *chip, -+ unsigned offset, int value); -+ void (*set)(struct gpio_chip *chip, -+ unsigned offset, int value); -+ void (*dbg_show)(struct seq_file *s, -+ struct gpio_chip *chip); -+ int base; -+ u16 ngpio; -+ unsigned can_sleep:1; -+}; -+ -+extern const char *gpiochip_is_requested(struct gpio_chip *chip, -+ unsigned offset); -+ -+/* add/remove chips */ -+extern int gpiochip_add(struct gpio_chip *chip); -+extern int __must_check gpiochip_remove(struct gpio_chip *chip); -+ -+ -+/* Always use the library code for GPIO management calls, -+ * or when sleeping may be involved. -+ */ -+extern int gpio_request(unsigned gpio, const char *label); -+extern void gpio_free(unsigned gpio); -+ -+extern int gpio_direction_input(unsigned gpio); -+extern int gpio_direction_output(unsigned gpio, int value); -+ -+extern int gpio_get_value_cansleep(unsigned gpio); -+extern void gpio_set_value_cansleep(unsigned gpio, int value); -+ -+ -+/* A platform's <asm/gpio.h> code may want to inline the I/O calls when -+ * the GPIO is constant and refers to some always-present controller, -+ * giving direct access to chip registers and tight bitbanging loops. -+ */ -+extern int __gpio_get_value(unsigned gpio); -+extern void __gpio_set_value(unsigned gpio, int value); -+ -+extern int __gpio_cansleep(unsigned gpio); -+ -+ -+#else -+ - /* platforms that don't directly support access to GPIOs through I2C, SPI, - * or other blocking infrastructure can use these wrappers. - */ -@@ -22,4 +118,6 @@ static inline void gpio_set_value_cansleep(unsigned gpio, int value) - gpio_set_value(gpio, value); - } - -+#endif -+ - #endif /* _ASM_GENERIC_GPIO_H */ --- -1.5.3.8 - |