From bb41458ba515f1296d12a87affceab482f795077 Mon Sep 17 00:00:00 2001
From: kaloz <kaloz@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Date: Wed, 28 Jan 2009 15:15:46 +0000
Subject: [PATCH] add IXP4xx GPIOLIB support based on Chris' patch

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@14241 3c298f89-4303-0410-b956-a3cf2f4a3e73
---
 .../patches-2.6.28/402-ixp4xx_gpiolib.patch   | 140 ++++++++++++++++++
 1 file changed, 140 insertions(+)
 create mode 100644 target/linux/ixp4xx/patches-2.6.28/402-ixp4xx_gpiolib.patch

diff --git a/target/linux/ixp4xx/patches-2.6.28/402-ixp4xx_gpiolib.patch b/target/linux/ixp4xx/patches-2.6.28/402-ixp4xx_gpiolib.patch
new file mode 100644
index 000000000..49726d6ea
--- /dev/null
+++ b/target/linux/ixp4xx/patches-2.6.28/402-ixp4xx_gpiolib.patch
@@ -0,0 +1,140 @@
+diff -ruN a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
+--- a/arch/arm/mach-ixp4xx/common.c	2008-10-08 20:24:05.000000000 -0700
++++ b/arch/arm/mach-ixp4xx/common.c	2009-01-16 20:55:10.000000000 -0800
+@@ -36,6 +36,7 @@
+ #include <asm/pgtable.h>
+ #include <asm/page.h>
+ #include <asm/irq.h>
++#include <asm/gpio.h>
+ 
+ #include <asm/mach/map.h>
+ #include <asm/mach/irq.h>
+@@ -374,12 +375,39 @@
+ unsigned long ixp4xx_exp_bus_size;
+ EXPORT_SYMBOL(ixp4xx_exp_bus_size);
+ 
++static int ixp4xx_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
++{
++	gpio_line_config(gpio, IXP4XX_GPIO_IN);
++	return 0;
++}
++EXPORT_SYMBOL(ixp4xx_gpio_direction_input);
++
++static int ixp4xx_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int level)
++{
++	gpio_line_set(gpio, level);
++	gpio_line_config(gpio, IXP4XX_GPIO_OUT);
++	return 0;
++}
++EXPORT_SYMBOL(ixp4xx_gpio_direction_output);
++
++static struct gpio_chip ixp4xx_gpio_chip = {
++	.label			= "IXP4XX_GPIO_CHIP",
++	.direction_input	= ixp4xx_gpio_direction_input,
++	.direction_output	= ixp4xx_gpio_direction_output,
++	.get			= gpio_get_value,
++	.set			= gpio_set_value,
++	.base			= 0,
++	.ngpio			= 16,
++};
++
+ void __init ixp4xx_sys_init(void)
+ {
+ 	ixp4xx_exp_bus_size = SZ_16M;
+ 
+ 	platform_add_devices(ixp4xx_devices, ARRAY_SIZE(ixp4xx_devices));
+ 
++	gpiochip_add(&ixp4xx_gpio_chip);
++
+ 	if (cpu_is_ixp46x()) {
+ 		int region;
+ 
+diff -ruN a/arch/arm/Kconfig b/arch/arm/Kconfig
+--- a/arch/arm/Kconfig	2009-01-18 19:45:37.000000000 +0100
++++ b/arch/arm/Kconfig	2009-01-28 15:30:22.000000000 +0100
+@@ -355,6 +355,7 @@
+ 	select GENERIC_GPIO
+ 	select GENERIC_TIME
+ 	select GENERIC_CLOCKEVENTS
++	select ARCH_WANT_OPTIONAL_GPIOLIB
+ 	select DMABOUNCE if PCI
+ 	help
+ 	  Support for Intel's IXP4XX (XScale) family of processors.
+diff -ruN a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig
+--- a/arch/arm/mach-ixp4xx/Kconfig	2008-12-31 10:29:21.000000000 -0800
++++ b/arch/arm/mach-ixp4xx/Kconfig	2009-01-16 15:17:54.000000000 -0800
+@@ -28,6 +28,7 @@
+ config MACH_CAMBRIA
+ 	bool "Cambria"
+ 	select PCI
++	select GPIOLIB
+ 	help
+ 	  Say 'Y' here if you want your kernel to support the Gateworks
+ 	  Cambria series. For more information on this platform,
+
+diff -ruN a/include/asm-arm/arch-ixp4xx/gpio.h b/include/asm-arm/arch-ixp4xx/gpio.h
+--- a/arch/arm/mach-ixp4xx/include/mach/gpio.h	2008-10-08 20:24:05.000000000 -0700
++++ b/arch/arm/mach-ixp4xx/include/mach/gpio.h	2009-01-16 20:55:25.000000000 -0800
+@@ -27,47 +27,31 @@
+ 
+ #include <linux/kernel.h>
+ #include <mach/hardware.h>
++#include <asm-generic/gpio.h>			/* cansleep wrappers */
+ 
+-static inline int gpio_request(unsigned gpio, const char *label)
+-{
+-	return 0;
+-}
+-
+-static inline void gpio_free(unsigned gpio)
+-{
+-	might_sleep();
+-
+-	return;
+-}
+-
+-static inline int gpio_direction_input(unsigned gpio)
+-{
+-	gpio_line_config(gpio, IXP4XX_GPIO_IN);
+-	return 0;
+-}
+-
+-static inline int gpio_direction_output(unsigned gpio, int level)
+-{
+-	gpio_line_set(gpio, level);
+-	gpio_line_config(gpio, IXP4XX_GPIO_OUT);
+-	return 0;
+-}
++#define NR_BUILTIN_GPIO 16
+ 
+ static inline int gpio_get_value(unsigned gpio)
+ {
+-	int value;
+-
+-	gpio_line_get(gpio, &value);
+-
+-	return value;
++	if (gpio < NR_BUILTIN_GPIO)
++	{
++		int value;
++		gpio_line_get(gpio, &value);
++		return value;
++	}
++	else
++		return __gpio_get_value(gpio);
+ }
+ 
+ static inline void gpio_set_value(unsigned gpio, int value)
+ {
+-	gpio_line_set(gpio, value);
++	if (gpio < NR_BUILTIN_GPIO)
++		gpio_line_set(gpio, value);
++	else
++		__gpio_set_value(gpio, value);
+ }
+ 
+-#include <asm-generic/gpio.h>			/* cansleep wrappers */
++#define gpio_cansleep __gpio_cansleep
+ 
+ extern int gpio_to_irq(int gpio);
+ extern int irq_to_gpio(int gpio);
-- 
2.20.1