public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH RFC] x86: Add user configurable GPIO-lib support
@ 2008-07-02  2:57 David Brownell
  2008-07-02  9:40 ` Michael Buesch
  0 siblings, 1 reply; 10+ messages in thread
From: David Brownell @ 2008-07-02  2:57 UTC (permalink / raw)
  To: lkml; +Cc: Florian Fainelli, Michael Buesch

More food for thought ... 

This makes the rdc321x support switch over to using gpiolib,
along with all of x86.  Quick'n'dirty.

It's perhaps best done in conjunction with something to
make GPIOLIB be user-configurable on systems where it's not
already selected by platform code.  The rdc321x stuff needs
more working, but this is a start.

- Dave

---
 arch/x86/Kconfig                            |    6 +
 arch/x86/mach-rdc321x/gpio.c                |  107 ++++++++--------------------
 arch/x86/mach-rdc321x/platform.c            |    3 
 include/asm-x86/gpio.h                      |   22 +++++
 include/asm-x86/mach-rdc321x/gpio.h         |   52 -------------
 include/asm-x86/mach-rdc321x/rdc321x_defs.h |    2 
 6 files changed, 62 insertions(+), 130 deletions(-)

--- a/arch/x86/Kconfig	2008-07-01 16:46:11.000000000 -0700
+++ b/arch/x86/Kconfig	2008-07-01 16:46:13.000000000 -0700
@@ -87,7 +87,10 @@ config GENERIC_HWEIGHT
 	def_bool y
 
 config GENERIC_GPIO
-	def_bool n
+	def_bool y
+
+config HAVE_GPIO_LIB
+	def_bool y
 
 config ARCH_MAY_HAVE_PC_FDC
 	def_bool y
@@ -325,7 +328,6 @@ config X86_RDC321X
 	depends on X86_32
 	select M486
 	select X86_REBOOTFIXUPS
-	select GENERIC_GPIO
 	select LEDS_CLASS
 	select LEDS_GPIO
 	select NEW_LEDS
--- a/arch/x86/mach-rdc321x/gpio.c	2008-07-01 16:46:11.000000000 -0700
+++ b/arch/x86/mach-rdc321x/gpio.c	2008-07-01 17:06:48.000000000 -0700
@@ -25,8 +25,9 @@
 #include <linux/io.h>
 #include <linux/types.h>
 #include <linux/module.h>
+#include <linux/gpio.h>
 
-#include <asm/gpio.h>
+#include <asm/mach-rdc321x/gpio.h>
 #include <asm/mach-rdc321x/rdc321x_defs.h>
 
 
@@ -38,8 +39,6 @@ static DEFINE_SPINLOCK(gpio_lock);
 static u32 gpio_data_reg1;
 static u32 gpio_data_reg2;
 
-static u32 gpio_request_data[2];
-
 
 static inline void rdc321x_conf_write(unsigned addr, u32 value)
 {
@@ -73,61 +72,8 @@ static void rdc321x_configure_gpio(unsig
 	spin_unlock_irqrestore(&gpio_lock, flags);
 }
 
-/* initially setup the 2 copies of the gpio data registers.
-   This function must be called by the platform setup code. */
-void __init rdc321x_gpio_setup()
-{
-	/* this might not be, what others (BIOS, bootloader, etc.)
-	   wrote to these registers before, but it's a good guess. Still
-	   better than just using 0xffffffff. */
-
-	gpio_data_reg1 = rdc321x_conf_read(RDC321X_GPIO_DATA_REG1);
-	gpio_data_reg2 = rdc321x_conf_read(RDC321X_GPIO_DATA_REG2);
-}
-
-/* determine, if gpio number is valid */
-static inline int rdc321x_is_gpio(unsigned gpio)
-{
-	return gpio <= RDC321X_MAX_GPIO;
-}
-
-/* request GPIO */
-int rdc_gpio_request(unsigned gpio, const char *label)
-{
-	unsigned long flags;
-
-	if (!rdc321x_is_gpio(gpio))
-		return -EINVAL;
-
-	spin_lock_irqsave(&gpio_lock, flags);
-	if (gpio_request_data[(gpio & 0x20) ? 1 : 0] & (1 << (gpio & 0x1f)))
-		goto inuse;
-	gpio_request_data[(gpio & 0x20) ? 1 : 0] |= (1 << (gpio & 0x1f));
-	spin_unlock_irqrestore(&gpio_lock, flags);
-
-	return 0;
-inuse:
-	spin_unlock_irqrestore(&gpio_lock, flags);
-	return -EINVAL;
-}
-EXPORT_SYMBOL(rdc_gpio_request);
-
-/* release previously-claimed GPIO */
-void rdc_gpio_free(unsigned gpio)
-{
-	unsigned long flags;
-
-	if (!rdc321x_is_gpio(gpio))
-		return;
-
-	spin_lock_irqsave(&gpio_lock, flags);
-	gpio_request_data[(gpio & 0x20) ? 1 : 0] &= ~(1 << (gpio & 0x1f));
-	spin_unlock_irqrestore(&gpio_lock, flags);
-}
-EXPORT_SYMBOL(rdc_gpio_free);
-
 /* read GPIO pin */
-int rdc_gpio_get_value(unsigned gpio)
+static int rdc_gpio_get_value(struct gpio_chip *g, unsigned gpio)
 {
 	u32 reg;
 	unsigned long flags;
@@ -139,56 +85,69 @@ int rdc_gpio_get_value(unsigned gpio)
 
 	return (1 << (gpio & 0x1f)) & reg ? 1 : 0;
 }
-EXPORT_SYMBOL(rdc_gpio_get_value);
 
 /* set GPIO pin to value */
-void rdc_gpio_set_value(unsigned gpio, int value)
+static void rdc_gpio_set_value(struct gpio_chip *g, unsigned gpio, int value)
 {
 	unsigned long flags;
 	u32 reg;
 
 	reg = 1 << (gpio & 0x1f);
+	spin_lock_irqsave(&gpio_lock, flags);
 	if (gpio < 32) {
-		spin_lock_irqsave(&gpio_lock, flags);
 		if (value)
 			gpio_data_reg1 |= reg;
 		else
 			gpio_data_reg1 &= ~reg;
 		rdc321x_conf_write(RDC321X_GPIO_DATA_REG1, gpio_data_reg1);
-		spin_unlock_irqrestore(&gpio_lock, flags);
 	} else {
-		spin_lock_irqsave(&gpio_lock, flags);
 		if (value)
 			gpio_data_reg2 |= reg;
 		else
 			gpio_data_reg2 &= ~reg;
 		rdc321x_conf_write(RDC321X_GPIO_DATA_REG2, gpio_data_reg2);
-		spin_unlock_irqrestore(&gpio_lock, flags);
 	}
+	spin_unlock_irqrestore(&gpio_lock, flags);
 }
-EXPORT_SYMBOL(rdc_gpio_set_value);
 
 /* configure GPIO pin as input */
-int rdc_gpio_direction_input(unsigned gpio)
+static int rdc_gpio_direction_input(struct gpio_chip *g, unsigned gpio)
 {
-	if (!rdc321x_is_gpio(gpio))
-		return -EINVAL;
-
 	rdc321x_configure_gpio(gpio);
 
 	return 0;
 }
-EXPORT_SYMBOL(rdc_gpio_direction_input);
 
 /* configure GPIO pin as output and set value */
-int rdc_gpio_direction_output(unsigned gpio, int value)
+static int rdc_gpio_direction_output(struct gpio_chip *g, unsigned gpio, int value)
 {
-	if (!rdc321x_is_gpio(gpio))
-		return -EINVAL;
-
 	gpio_set_value(gpio, value);
 	rdc321x_configure_gpio(gpio);
 
 	return 0;
 }
-EXPORT_SYMBOL(rdc_gpio_direction_output);
+
+static struct gpio_chip rdc_gpio_chip = {
+	.label			= "rdc321x",
+	.direction_input	= rdc_gpio_direction_input,
+	.get			= rdc_gpio_get_value,
+	.direction_output	= rdc_gpio_direction_output,
+	.set			= rdc_gpio_set_value,
+	.base			= 0,
+	.ngpio			= RDC321X_MAX_GPIO + 1,
+};
+
+/* initially setup the 2 copies of the gpio data registers.
+   This function must be called by the platform setup code. */
+void __init rdc321x_gpio_setup()
+{
+	/* this might not be, what others (BIOS, bootloader, etc.)
+	   wrote to these registers before, but it's a good guess. Still
+	   better than just using 0xffffffff. */
+
+	gpio_data_reg1 = rdc321x_conf_read(RDC321X_GPIO_DATA_REG1);
+	gpio_data_reg2 = rdc321x_conf_read(RDC321X_GPIO_DATA_REG2);
+
+	gpiochip_add(&rdc_gpio_chip);
+}
+
--- a/arch/x86/mach-rdc321x/platform.c	2008-07-01 16:46:11.000000000 -0700
+++ b/arch/x86/mach-rdc321x/platform.c	2008-07-01 16:46:13.000000000 -0700
@@ -27,8 +27,7 @@
 #include <linux/platform_device.h>
 #include <linux/version.h>
 #include <linux/leds.h>
-
-#include <asm/gpio.h>
+#include <linux/gpio.h>
 
 /* LEDS */
 static struct gpio_led default_leds[] = {
--- a/include/asm-x86/gpio.h	2008-07-01 16:46:11.000000000 -0700
+++ b/include/asm-x86/gpio.h	2008-07-01 16:46:13.000000000 -0700
@@ -1,6 +1,26 @@
 #ifndef _ASM_I386_GPIO_H
 #define _ASM_I386_GPIO_H
 
-#include <gpio.h>
+#include <linux/errno.h>
+
+#ifdef CONFIG_X86_RDC321X
+#include <asm/mach-rdc321x/gpio.h>
+#endif
+
+#include <asm-generic/gpio.h>
+
+#define gpio_get_value	__gpio_get_value
+#define gpio_set_value	__gpio_set_value
+#define gpio_cansleep	__gpio_cansleep
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+	return -ENOSYS;
+}
+
+static inline int irq_to_gpio(unsigned irq)
+{
+	return -EINVAL;
+}
 
 #endif /* _ASM_I386_GPIO_H */
--- a/include/asm-x86/mach-rdc321x/gpio.h	2008-07-01 16:46:11.000000000 -0700
+++ b/include/asm-x86/mach-rdc321x/gpio.h	2008-07-01 17:08:38.000000000 -0700
@@ -1,57 +1,11 @@
 #ifndef _RDC321X_GPIO_H
 #define _RDC321X_GPIO_H
 
-extern int rdc_gpio_get_value(unsigned gpio);
-extern void rdc_gpio_set_value(unsigned gpio, int value);
-extern int rdc_gpio_direction_input(unsigned gpio);
-extern int rdc_gpio_direction_output(unsigned gpio, int value);
-extern int rdc_gpio_request(unsigned gpio, const char *label);
-extern void rdc_gpio_free(unsigned gpio);
 extern void __init rdc321x_gpio_setup(void);
 
-/* Wrappers for the arch-neutral GPIO API */
-
-static inline int gpio_request(unsigned gpio, const char *label)
-{
-	return rdc_gpio_request(gpio, label);
-}
-
-static inline void gpio_free(unsigned gpio)
-{
-	rdc_gpio_free(gpio);
-}
-
-static inline int gpio_direction_input(unsigned gpio)
-{
-	return rdc_gpio_direction_input(gpio);
-}
-
-static inline int gpio_direction_output(unsigned gpio, int value)
-{
-	return rdc_gpio_direction_output(gpio, value);
-}
-
-static inline int gpio_get_value(unsigned gpio)
-{
-	return rdc_gpio_get_value(gpio);
-}
-
-static inline void gpio_set_value(unsigned gpio, int value)
-{
-	rdc_gpio_set_value(gpio, value);
-}
-
-static inline int gpio_to_irq(unsigned gpio)
-{
-	return gpio;
-}
-
-static inline int irq_to_gpio(unsigned irq)
-{
-	return irq;
-}
+#define RDC321X_MAX_GPIO	58
 
-/* For cansleep */
-#include <asm-generic/gpio.h>
+/* allow for a few external GPIO expanders */
+#define	ARCH_NR_GPIOS		(RDC321X_MAX_GPIO + 64)
 
 #endif /* _RDC321X_GPIO_H_ */
--- a/include/asm-x86/mach-rdc321x/rdc321x_defs.h	2008-07-01 16:46:11.000000000 -0700
+++ b/include/asm-x86/mach-rdc321x/rdc321x_defs.h	2008-07-01 16:46:13.000000000 -0700
@@ -8,5 +8,3 @@
 #define RDC321X_GPIO_CTRL_REG2	0x84
 #define RDC321X_GPIO_DATA_REG1	0x4c
 #define RDC321X_GPIO_DATA_REG2	0x88
-
-#define RDC321X_MAX_GPIO	58

^ permalink raw reply	[flat|nested] 10+ messages in thread
* [PATCH RFC] x86: Add user configurable GPIO-lib support
@ 2008-07-01 10:49 Michael Buesch
  2008-07-01 11:04 ` Ingo Molnar
  0 siblings, 1 reply; 10+ messages in thread
From: Michael Buesch @ 2008-07-01 10:49 UTC (permalink / raw)
  To: tglx, mingo, hpa; +Cc: linux-kernel

So this adds user-configurable GPIO support through gpiolib
on subarchitectures that do not implement a GPIO implementation, yet.
Currently that's everything except X86_RDC321X.

The advantage of this is to make it possible to use generic PCI (or
other bus) GPIO extention cards in standard PCs through the standard
GPIO API.

If another subarch implements its own GPIO, it needs to add
itself as an inverted dependency to GPIO_USERSELECTION to make
sure the user does not enable two GPIO API implementations.

About the asm-x86/gpio.h:
I'm not sure what this <gpio.h> include currently is.
Can somebody explain that to me? Where is this supposed
to include a gpio.h file from?


What's your opinion on this?


Index: wireless-testing/arch/x86/Kconfig
===================================================================
--- wireless-testing.orig/arch/x86/Kconfig	2008-06-30 23:00:29.000000000 +0200
+++ wireless-testing/arch/x86/Kconfig	2008-06-30 23:07:04.000000000 +0200
@@ -1675,6 +1675,19 @@
 
 source "drivers/pci/hotplug/Kconfig"
 
+config GPIO_USERSELECTION
+	bool "Enable generic GPIO support through gpiolib"
+	depends on !X86_RDC321X
+	select GENERIC_GPIO
+	select HAVE_GPIO_LIB
+	help
+	  This enables GPIO support through the generic GPIO library.
+	  You only need to enable this, if you also want to enable
+	  one or more of the GPIO expansion card drivers in
+	  "Device Drivers/GPIO Support".
+
+	  If unsure, say N.
+
 endmenu
 
 
Index: wireless-testing/include/asm-x86/gpio.h
===================================================================
--- wireless-testing.orig/include/asm-x86/gpio.h	2008-06-30 23:28:55.000000000 +0200
+++ wireless-testing/include/asm-x86/gpio.h	2008-06-30 23:36:20.000000000 +0200
@@ -1,6 +1,62 @@
+/*
+ * Generic GPIO API implementation for x86.
+ *
+ * Derived from the generic GPIO API for powerpc:
+ *
+ * Copyright (c) 2007-2008  MontaVista Software, Inc.
+ *
+ * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
 #ifndef _ASM_I386_GPIO_H
 #define _ASM_I386_GPIO_H
 
+#ifdef CONFIG_X86_RDC321X
 #include <gpio.h>
+#else /* CONFIG_X86_RDC321X */
+
+#include <asm-generic/gpio.h>
+
+#ifdef CONFIG_HAVE_GPIO_LIB
+
+/*
+ * Just call gpiolib.
+ */
+static inline int gpio_get_value(unsigned int gpio)
+{
+	return __gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned int gpio, int value)
+{
+	__gpio_set_value(gpio, value);
+}
+
+static inline int gpio_cansleep(unsigned int gpio)
+{
+	return __gpio_cansleep(gpio);
+}
+
+/*
+ * Not implemented, yet.
+ */
+static inline int gpio_to_irq(unsigned int gpio)
+{
+	return -ENOSYS;
+}
+
+static inline int irq_to_gpio(unsigned int irq)
+{
+	return -EINVAL;
+}
+
+#endif /* CONFIG_HAVE_GPIO_LIB */
+
+#endif /* CONFIG_X86_RDC321X */
 
 #endif /* _ASM_I386_GPIO_H */

-- 
Greetings Michael.

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

end of thread, other threads:[~2008-07-02  9:40 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-07-02  2:57 [PATCH RFC] x86: Add user configurable GPIO-lib support David Brownell
2008-07-02  9:40 ` Michael Buesch
  -- strict thread matches above, loose matches on Subject: below --
2008-07-01 10:49 Michael Buesch
2008-07-01 11:04 ` Ingo Molnar
2008-07-01 11:13   ` Michael Buesch
2008-07-01 11:19     ` Ingo Molnar
2008-07-01 11:27       ` Michael Buesch
2008-07-01 23:05       ` Michael Buesch
2008-07-01 12:55   ` Florian Fainelli
2008-07-01 14:26     ` Ingo Molnar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox