diff mbox

[U-Boot,v1] bfin: Move gpio support for bf54x and bf60x into the generic driver folder.

Message ID 1367474125-4702-1-git-send-email-sonic.adi@gmail.com
State Accepted
Delegated to: Sonic Zhang
Headers show

Commit Message

Sonic Zhang May 2, 2013, 5:55 a.m. UTC
From: Sonic Zhang <sonic.zhang@analog.com>

The gpio spec for bf54x and bf60x differ a lot from the old gpio driver for bf5xx.
A lot of machine macros are used to accomodate both code in one gpio driver.
This patch split the old gpio driver and move new gpio2 support to the generic
gpio driver folder.

- To enable gpio2 driver, macro CONFIG_ADI_GPIO2 should be defined in the board's
config header file.
- The gpio2 driver supports bf54x, bf60x and future ADI processors, while the
older gpio driver supports bf50x, bf51x, bf52x, bf53x and bf561.
- All blackfin specific gpio function names are replaced by the generic gpio APIs.

Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
---
 arch/blackfin/cpu/Makefile          |    2 +-
 arch/blackfin/cpu/gpio.c            |  145 ++----------
 arch/blackfin/include/asm/gpio.h    |   62 +----
 arch/blackfin/include/asm/portmux.h |    5 -
 drivers/gpio/Makefile               |    1 +
 drivers/gpio/adi_gpio2.c            |  440 +++++++++++++++++++++++++++++++++++
 include/configs/bf548-ezkit.h       |    2 +
 include/configs/bf609-ezkit.h       |    2 +
 include/configs/bfin_adi_common.h   |    4 +-
 9 files changed, 479 insertions(+), 184 deletions(-)
 create mode 100644 drivers/gpio/adi_gpio2.c

Comments

Mike Frysinger May 2, 2013, 4:23 p.m. UTC | #1
On Thursday 02 May 2013 01:55:25 Sonic Zhang wrote:
> The gpio spec for bf54x and bf60x differ a lot from the old gpio driver for
> bf5xx. A lot of machine macros are used to accomodate both code in one
> gpio driver. This patch split the old gpio driver and move new gpio2
> support to the generic gpio driver folder.
> 
> - To enable gpio2 driver, macro CONFIG_ADI_GPIO2 should be defined in the
> board's config header file.
> - The gpio2 driver supports bf54x, bf60x and future ADI processors, while
> the older gpio driver supports bf50x, bf51x, bf52x, bf53x and bf561.
> - All blackfin specific gpio function names are replaced by the generic
> gpio APIs.

the code in u-boot was written so as to make direct import from the kernel 
trivial.  that way there is only one code base to maintain -- the kernel.  
last i looked, you hadn't split the drivers in the kernel, which means things 
are now diverging.
-mike
Sonic Zhang May 3, 2013, 4:53 a.m. UTC | #2
Hi Mike,

On Fri, May 3, 2013 at 12:23 AM, Mike Frysinger <vapier@gentoo.org> wrote:
> On Thursday 02 May 2013 01:55:25 Sonic Zhang wrote:
>> The gpio spec for bf54x and bf60x differ a lot from the old gpio driver for
>> bf5xx. A lot of machine macros are used to accomodate both code in one
>> gpio driver. This patch split the old gpio driver and move new gpio2
>> support to the generic gpio driver folder.
>>
>> - To enable gpio2 driver, macro CONFIG_ADI_GPIO2 should be defined in the
>> board's config header file.
>> - The gpio2 driver supports bf54x, bf60x and future ADI processors, while
>> the older gpio driver supports bf50x, bf51x, bf52x, bf53x and bf561.
>> - All blackfin specific gpio function names are replaced by the generic
>> gpio APIs.
>
> the code in u-boot was written so as to make direct import from the kernel
> trivial.  that way there is only one code base to maintain -- the kernel.
> last i looked, you hadn't split the drivers in the kernel, which means things
> are now diverging.

Don't worry. I will do it in Linux kernel soon after this is merged into u-boot.

Regards,

Sonic
diff mbox

Patch

diff --git a/arch/blackfin/cpu/Makefile b/arch/blackfin/cpu/Makefile
index 929fc8b..1421cb2 100644
--- a/arch/blackfin/cpu/Makefile
+++ b/arch/blackfin/cpu/Makefile
@@ -18,7 +18,7 @@  CEXTRA   := initcode.o
 SEXTRA   := start.o
 SOBJS    := interrupt.o cache.o
 COBJS-y  += cpu.o
-COBJS-y  += gpio.o
+COBJS-$(CONFIG_ADI_GPIO1) += gpio.o
 COBJS-y  += interrupts.o
 COBJS-$(CONFIG_JTAG_CONSOLE) += jtag-console.o
 COBJS-y  += os_log.o
diff --git a/arch/blackfin/cpu/gpio.c b/arch/blackfin/cpu/gpio.c
index f684be5..f74a0b7 100644
--- a/arch/blackfin/cpu/gpio.c
+++ b/arch/blackfin/cpu/gpio.c
@@ -1,5 +1,6 @@ 
 /*
- * GPIO Abstraction Layer
+ * ADI GPIO1 Abstraction Layer
+ * Support BF50x, BF51x, BF52x, BF53x and BF561 only.
  *
  * Copyright 2006-2010 Analog Devices Inc.
  *
@@ -55,25 +56,6 @@  static struct gpio_port_t * const gpio_array[] = {
 	(struct gpio_port_t *) FIO0_FLAG_D,
 	(struct gpio_port_t *) FIO1_FLAG_D,
 	(struct gpio_port_t *) FIO2_FLAG_D,
-#elif defined(CONFIG_BF54x)
-	(struct gpio_port_t *)PORTA_FER,
-	(struct gpio_port_t *)PORTB_FER,
-	(struct gpio_port_t *)PORTC_FER,
-	(struct gpio_port_t *)PORTD_FER,
-	(struct gpio_port_t *)PORTE_FER,
-	(struct gpio_port_t *)PORTF_FER,
-	(struct gpio_port_t *)PORTG_FER,
-	(struct gpio_port_t *)PORTH_FER,
-	(struct gpio_port_t *)PORTI_FER,
-	(struct gpio_port_t *)PORTJ_FER,
-#elif defined(CONFIG_BF60x)
-	(struct gpio_port_t *)PORTA_FER,
-	(struct gpio_port_t *)PORTB_FER,
-	(struct gpio_port_t *)PORTC_FER,
-	(struct gpio_port_t *)PORTD_FER,
-	(struct gpio_port_t *)PORTE_FER,
-	(struct gpio_port_t *)PORTF_FER,
-	(struct gpio_port_t *)PORTG_FER,
 #else
 # error no gpio arrays defined
 #endif
@@ -174,12 +156,6 @@  DECLARE_RESERVED_MAP(peri, gpio_bank(MAX_RESOURCES));
 
 inline int check_gpio(unsigned gpio)
 {
-#if defined(CONFIG_BF54x)
-	if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15
-	    || gpio == GPIO_PH14 || gpio == GPIO_PH15
-	    || gpio == GPIO_PJ14 || gpio == GPIO_PJ15)
-		return -EINVAL;
-#endif
 	if (gpio >= MAX_BLACKFIN_GPIOS)
 		return -EINVAL;
 	return 0;
@@ -218,18 +194,6 @@  static void port_setup(unsigned gpio, unsigned short usage)
 	else
 		*port_fer[gpio_bank(gpio)] |= gpio_bit(gpio);
 	SSYNC();
-#elif defined(CONFIG_BF54x)
-	if (usage == GPIO_USAGE)
-		gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio);
-	else
-		gpio_array[gpio_bank(gpio)]->port_fer |= gpio_bit(gpio);
-	SSYNC();
-#elif defined(CONFIG_BF60x)
-	if (usage == GPIO_USAGE)
-		gpio_array[gpio_bank(gpio)]->port_fer_clear = gpio_bit(gpio);
-	else
-		gpio_array[gpio_bank(gpio)]->port_fer_set = gpio_bit(gpio);
-	SSYNC();
 #endif
 }
 
@@ -304,30 +268,6 @@  static void portmux_setup(unsigned short per)
 		}
 	}
 }
-#elif defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
-inline void portmux_setup(unsigned short per)
-{
-	u32 pmux;
-	u16 ident = P_IDENT(per);
-	u16 function = P_FUNCT2MUX(per);
-
-	pmux = gpio_array[gpio_bank(ident)]->port_mux;
-
-	pmux &= ~(0x3 << (2 * gpio_sub_n(ident)));
-	pmux |= (function & 0x3) << (2 * gpio_sub_n(ident));
-
-	gpio_array[gpio_bank(ident)]->port_mux = pmux;
-}
-
-inline u16 get_portmux(unsigned short per)
-{
-	u32 pmux;
-	u16 ident = P_IDENT(per);
-
-	pmux = gpio_array[gpio_bank(ident)]->port_mux;
-
-	return (pmux >> (2 * gpio_sub_n(ident)) & 0x3);
-}
 #elif defined(CONFIG_BF52x) || defined(CONFIG_BF51x)
 inline void portmux_setup(unsigned short per)
 {
@@ -344,7 +284,6 @@  inline void portmux_setup(unsigned short per)
 # define portmux_setup(...)  do { } while (0)
 #endif
 
-#if !defined(CONFIG_BF54x) && !defined(CONFIG_BF60x)
 /***********************************************************
 *
 * FUNCTIONS: Blackfin General Purpose Ports Access Functions
@@ -491,15 +430,6 @@  GET_GPIO_P(both)
 GET_GPIO_P(maska)
 GET_GPIO_P(maskb)
 
-#else /* CONFIG_BF54x */
-
-unsigned short get_gpio_dir(unsigned gpio)
-{
-	return (0x01 & (gpio_array[gpio_bank(gpio)]->dir_clear >> gpio_sub_n(gpio)));
-}
-
-#endif /* CONFIG_BF54x */
-
 /***********************************************************
 *
 * FUNCTIONS:	Blackfin Peripheral Resource Allocation
@@ -548,11 +478,7 @@  int peripheral_request(unsigned short per, const char *label)
 		 * be requested and used by several drivers
 		 */
 
-#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
-		if (!((per & P_MAYSHARE) && get_portmux(per) == P_FUNCT2MUX(per))) {
-#else
 		if (!(per & P_MAYSHARE)) {
-#endif
 			/*
 			 * Allow that the identical pin function can
 			 * be requested from the same driver twice
@@ -641,7 +567,7 @@  void peripheral_free_list(const unsigned short per[])
 * MODIFICATION HISTORY :
 **************************************************************/
 
-int bfin_gpio_request(unsigned gpio, const char *label)
+int gpio_request(unsigned gpio, const char *label)
 {
 	if (check_gpio(gpio) < 0)
 		return -EINVAL;
@@ -665,11 +591,9 @@  int bfin_gpio_request(unsigned gpio, const char *label)
 		       gpio, get_label(gpio));
 		return -EBUSY;
 	}
-#if !defined(CONFIG_BF54x) && !defined(CONFIG_BF60x)
 	else {	/* Reset POLAR setting when acquiring a gpio for the first time */
 		set_gpio_polar(gpio, 0);
 	}
-#endif
 
 	reserve(gpio, gpio);
 	set_label(gpio, label);
@@ -679,27 +603,27 @@  int bfin_gpio_request(unsigned gpio, const char *label)
 	return 0;
 }
 
-#ifdef CONFIG_BFIN_GPIO_TRACK
-void bfin_gpio_free(unsigned gpio)
+int gpio_free(unsigned gpio)
 {
 	if (check_gpio(gpio) < 0)
-		return;
+		return -1;
 
 	if (unlikely(!is_reserved(gpio, gpio, 0))) {
 		gpio_error(gpio);
-		return;
+		return -1;
 	}
 
 	unreserve(gpio, gpio);
 
 	set_label(gpio, "free");
+
+	return 0;
 }
-#endif
 
-#ifdef BFIN_SPECIAL_GPIO_BANKS
+#ifdef ADI_SPECIAL_GPIO_BANKS
 DECLARE_RESERVED_MAP(special_gpio, gpio_bank(MAX_RESOURCES));
 
-int bfin_special_gpio_request(unsigned gpio, const char *label)
+int special_gpio_request(unsigned gpio, const char *label)
 {
 	/*
 	 * Allow that the identical GPIO can
@@ -731,7 +655,7 @@  int bfin_special_gpio_request(unsigned gpio, const char *label)
 	return 0;
 }
 
-void bfin_special_gpio_free(unsigned gpio)
+void special_gpio_free(unsigned gpio)
 {
 	if (unlikely(!is_reserved(special_gpio, gpio, 0))) {
 		gpio_error(gpio);
@@ -744,21 +668,13 @@  void bfin_special_gpio_free(unsigned gpio)
 }
 #endif
 
-static inline void __bfin_gpio_direction_input(unsigned gpio)
+static inline void __gpio_direction_input(unsigned gpio)
 {
-#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
-	gpio_array[gpio_bank(gpio)]->dir_clear = gpio_bit(gpio);
-#else
 	gpio_array[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio);
-#endif
-#if defined(CONFIG_BF60x)
-	gpio_array[gpio_bank(gpio)]->inen_set = gpio_bit(gpio);
-#else
 	gpio_array[gpio_bank(gpio)]->inen |= gpio_bit(gpio);
-#endif
 }
 
-int bfin_gpio_direction_input(unsigned gpio)
+int gpio_direction_input(unsigned gpio)
 {
 	unsigned long flags;
 
@@ -768,31 +684,24 @@  int bfin_gpio_direction_input(unsigned gpio)
 	}
 
 	local_irq_save(flags);
-	__bfin_gpio_direction_input(gpio);
+	__gpio_direction_input(gpio);
 	AWA_DUMMY_READ(inen);
 	local_irq_restore(flags);
 
 	return 0;
 }
 
-void bfin_gpio_toggle_value(unsigned gpio)
-{
-#ifdef CONFIG_BF54x
-	gpio_set_value(gpio, !gpio_get_value(gpio));
-#else
-	gpio_array[gpio_bank(gpio)]->toggle = gpio_bit(gpio);
-#endif
-}
-
-void bfin_gpio_set_value(unsigned gpio, int arg)
+int gpio_set_value(unsigned gpio, int arg)
 {
 	if (arg)
 		gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio);
 	else
 		gpio_array[gpio_bank(gpio)]->data_clear = gpio_bit(gpio);
+
+	return 0;
 }
 
-int bfin_gpio_direction_output(unsigned gpio, int value)
+int gpio_direction_output(unsigned gpio, int value)
 {
 	unsigned long flags;
 
@@ -803,17 +712,9 @@  int bfin_gpio_direction_output(unsigned gpio, int value)
 
 	local_irq_save(flags);
 
-#if defined(CONFIG_BF60x)
-	gpio_array[gpio_bank(gpio)]->inen_clear = gpio_bit(gpio);
-#else
 	gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio);
-#endif
 	gpio_set_value(gpio, value);
-#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
-	gpio_array[gpio_bank(gpio)]->dir_set = gpio_bit(gpio);
-#else
 	gpio_array[gpio_bank(gpio)]->dir |= gpio_bit(gpio);
-#endif
 
 	AWA_DUMMY_READ(dir);
 	local_irq_restore(flags);
@@ -821,11 +722,8 @@  int bfin_gpio_direction_output(unsigned gpio, int value)
 	return 0;
 }
 
-int bfin_gpio_get_value(unsigned gpio)
+int gpio_get_value(unsigned gpio)
 {
-#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x)
-	return (1 & (gpio_array[gpio_bank(gpio)]->data >> gpio_sub_n(gpio)));
-#else
 	unsigned long flags;
 
 	if (unlikely(get_gpio_edge(gpio))) {
@@ -838,7 +736,6 @@  int bfin_gpio_get_value(unsigned gpio)
 		return ret;
 	} else
 		return get_gpio_data(gpio);
-#endif
 }
 
 /* If we are booting from SPI and our board lacks a strong enough pull up,
@@ -860,8 +757,7 @@  void bfin_reset_boot_spi_cs(unsigned short pin)
 	udelay(1);
 }
 
-#ifdef CONFIG_BFIN_GPIO_TRACK
-void bfin_gpio_labels(void)
+void gpio_labels(void)
 {
 	int c, gpio;
 
@@ -877,4 +773,3 @@  void bfin_gpio_labels(void)
 			continue;
 	}
 }
-#endif
diff --git a/arch/blackfin/include/asm/gpio.h b/arch/blackfin/include/asm/gpio.h
index 05131b5..58a6191 100644
--- a/arch/blackfin/include/asm/gpio.h
+++ b/arch/blackfin/include/asm/gpio.h
@@ -7,6 +7,8 @@ 
 #ifndef __ARCH_BLACKFIN_GPIO_H__
 #define __ARCH_BLACKFIN_GPIO_H__
 
+#include <asm-generic/gpio.h>
+
 #define gpio_bank(x)	((x) >> 4)
 #define gpio_bit(x)	(1<<((x) & 0xF))
 #define gpio_sub_n(x)	((x) & 0xF)
@@ -65,10 +67,11 @@ 
 
 #define PERIPHERAL_USAGE 1
 #define GPIO_USAGE 0
+#define MAX_GPIOS MAX_BLACKFIN_GPIOS
 
 #ifndef __ASSEMBLY__
 
-#if !defined(CONFIG_BF54x) && !defined(CONFIG_BF60x)
+#ifdef CONFIG_ADI_GPIO1
 void set_gpio_dir(unsigned, unsigned short);
 void set_gpio_inen(unsigned, unsigned short);
 void set_gpio_polar(unsigned, unsigned short);
@@ -140,61 +143,16 @@  struct gpio_port_t {
 };
 #endif
 
-#ifdef CONFIG_BFIN_GPIO_TRACK
-void bfin_gpio_labels(void);
-void bfin_gpio_free(unsigned gpio);
-#else
-#define bfin_gpio_labels()
-#define bfin_gpio_free(gpio)
-#define bfin_gpio_request(gpio, label) bfin_gpio_request(gpio)
-#define bfin_special_gpio_request(gpio, label) bfin_special_gpio_request(gpio)
-#endif
-
-#ifdef BFIN_SPECIAL_GPIO_BANKS
-void bfin_special_gpio_free(unsigned gpio);
-int bfin_special_gpio_request(unsigned gpio, const char *label);
+#ifdef ADI_SPECIAL_GPIO_BANKS
+void special_gpio_free(unsigned gpio);
+int special_gpio_request(unsigned gpio, const char *label);
 #endif
 
-int bfin_gpio_request(unsigned gpio, const char *label);
-int bfin_gpio_direction_input(unsigned gpio);
-int bfin_gpio_direction_output(unsigned gpio, int value);
-int bfin_gpio_get_value(unsigned gpio);
-void bfin_gpio_set_value(unsigned gpio, int value);
-void bfin_gpio_toggle_value(unsigned gpio);
-
-static inline int gpio_request(unsigned gpio, const char *label)
-{
-	return bfin_gpio_request(gpio, label);
-}
-
-static inline void gpio_free(unsigned gpio)
-{
-	return bfin_gpio_free(gpio);
-}
-
-static inline int gpio_direction_input(unsigned gpio)
-{
-	return bfin_gpio_direction_input(gpio);
-}
-
-static inline int gpio_direction_output(unsigned gpio, int value)
-{
-	return bfin_gpio_direction_output(gpio, value);
-}
-
-static inline int gpio_get_value(unsigned gpio)
-{
-	return bfin_gpio_get_value(gpio);
-}
-
-static inline void gpio_set_value(unsigned gpio, int value)
-{
-	return bfin_gpio_set_value(gpio, value);
-}
+void gpio_labels(void);
 
 static inline int gpio_is_valid(int number)
 {
-	return number >= 0 && number < MAX_BLACKFIN_GPIOS;
+	return number >= 0 && number < MAX_GPIOS;
 }
 
 #include <linux/ctype.h>
@@ -248,7 +206,7 @@  static inline int name_to_gpio(const char *name)
 }
 #define name_to_gpio(n) name_to_gpio(n)
 
-#define gpio_status() bfin_gpio_labels()
+#define gpio_status() gpio_labels()
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/blackfin/include/asm/portmux.h b/arch/blackfin/include/asm/portmux.h
index 300ef44..003694b 100644
--- a/arch/blackfin/include/asm/portmux.h
+++ b/arch/blackfin/include/asm/portmux.h
@@ -17,11 +17,6 @@ 
 #define P_MAYSHARE	0x2000
 #define P_DONTCARE	0x1000
 
-#ifndef CONFIG_BFIN_GPIO_TRACK
-#define peripheral_request(per, label) peripheral_request(per)
-#define peripheral_request_list(per, label) peripheral_request_list(per)
-#endif
-
 #ifndef __ASSEMBLY__
 
 int peripheral_request(unsigned short per, const char *label);
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 2d97b4f..5d2a1d4 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -46,6 +46,7 @@  COBJS-$(CONFIG_OMAP_GPIO)	+= omap_gpio.o
 COBJS-$(CONFIG_DB8500_GPIO)	+= db8500_gpio.o
 COBJS-$(CONFIG_BCM2835_GPIO)	+= bcm2835_gpio.o
 COBJS-$(CONFIG_S3C2440_GPIO)	+= s3c2440_gpio.o
+COBJS-$(CONFIG_ADI_GPIO2)	+= adi_gpio2.o
 
 COBJS	:= $(COBJS-y)
 SRCS 	:= $(COBJS:.o=.c)
diff --git a/drivers/gpio/adi_gpio2.c b/drivers/gpio/adi_gpio2.c
new file mode 100644
index 0000000..7a034eb
--- /dev/null
+++ b/drivers/gpio/adi_gpio2.c
@@ -0,0 +1,440 @@ 
+/*
+ * ADI GPIO2 Abstraction Layer
+ * Support BF54x, BF60x and future processors.
+ *
+ * Copyright 2008-2013 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later
+ */
+
+#include <common.h>
+#include <asm/errno.h>
+#include <asm/gpio.h>
+#include <asm/portmux.h>
+
+static struct gpio_port_t * const gpio_array[] = {
+	(struct gpio_port_t *)PORTA_FER,
+	(struct gpio_port_t *)PORTB_FER,
+	(struct gpio_port_t *)PORTC_FER,
+	(struct gpio_port_t *)PORTD_FER,
+	(struct gpio_port_t *)PORTE_FER,
+	(struct gpio_port_t *)PORTF_FER,
+	(struct gpio_port_t *)PORTG_FER,
+#if defined(CONFIG_BF54x)
+	(struct gpio_port_t *)PORTH_FER,
+	(struct gpio_port_t *)PORTI_FER,
+	(struct gpio_port_t *)PORTJ_FER,
+#endif
+};
+
+#define RESOURCE_LABEL_SIZE	16
+
+static struct str_ident {
+	char name[RESOURCE_LABEL_SIZE];
+} str_ident[MAX_RESOURCES];
+
+static void gpio_error(unsigned gpio)
+{
+	printf("adi_gpio2: GPIO %d wasn't requested!\n", gpio);
+}
+
+static void set_label(unsigned short ident, const char *label)
+{
+	if (label) {
+		strncpy(str_ident[ident].name, label,
+			RESOURCE_LABEL_SIZE);
+		str_ident[ident].name[RESOURCE_LABEL_SIZE - 1] = 0;
+	}
+}
+
+static char *get_label(unsigned short ident)
+{
+	return *str_ident[ident].name ? str_ident[ident].name : "UNKNOWN";
+}
+
+static int cmp_label(unsigned short ident, const char *label)
+{
+	if (label == NULL)
+		printf("adi_gpio2: please provide none-null label\n");
+
+	if (label)
+		return strcmp(str_ident[ident].name, label);
+	else
+		return -EINVAL;
+}
+
+#define map_entry(m, i)      reserved_##m##_map[gpio_bank(i)]
+#define is_reserved(m, i, e) (map_entry(m, i) & gpio_bit(i))
+#define reserve(m, i)        (map_entry(m, i) |= gpio_bit(i))
+#define unreserve(m, i)      (map_entry(m, i) &= ~gpio_bit(i))
+#define DECLARE_RESERVED_MAP(m, c) unsigned short reserved_##m##_map[c]
+
+static DECLARE_RESERVED_MAP(gpio, GPIO_BANK_NUM);
+static DECLARE_RESERVED_MAP(peri, gpio_bank(MAX_RESOURCES));
+
+inline int check_gpio(unsigned gpio)
+{
+#if defined(CONFIG_BF54x)
+	if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15 ||
+		gpio == GPIO_PH14 || gpio == GPIO_PH15 ||
+		gpio == GPIO_PJ14 || gpio == GPIO_PJ15)
+		return -EINVAL;
+#endif
+	if (gpio >= MAX_GPIOS)
+		return -EINVAL;
+	return 0;
+}
+
+static void port_setup(unsigned gpio, unsigned short usage)
+{
+#if defined(CONFIG_BF54x)
+	if (usage == GPIO_USAGE)
+		gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio);
+	else
+		gpio_array[gpio_bank(gpio)]->port_fer |= gpio_bit(gpio);
+#else
+	if (usage == GPIO_USAGE)
+		gpio_array[gpio_bank(gpio)]->port_fer_clear = gpio_bit(gpio);
+	else
+		gpio_array[gpio_bank(gpio)]->port_fer_set = gpio_bit(gpio);
+#endif
+	SSYNC();
+}
+
+inline void portmux_setup(unsigned short per)
+{
+	u32 pmux;
+	u16 ident = P_IDENT(per);
+	u16 function = P_FUNCT2MUX(per);
+
+	pmux = gpio_array[gpio_bank(ident)]->port_mux;
+
+	pmux &= ~(0x3 << (2 * gpio_sub_n(ident)));
+	pmux |= (function & 0x3) << (2 * gpio_sub_n(ident));
+
+	gpio_array[gpio_bank(ident)]->port_mux = pmux;
+}
+
+inline u16 get_portmux(unsigned short per)
+{
+	u32 pmux;
+	u16 ident = P_IDENT(per);
+
+	pmux = gpio_array[gpio_bank(ident)]->port_mux;
+
+	return pmux >> (2 * gpio_sub_n(ident)) & 0x3;
+}
+
+unsigned short get_gpio_dir(unsigned gpio)
+{
+	return 0x01 &
+		(gpio_array[gpio_bank(gpio)]->dir_clear >> gpio_sub_n(gpio));
+}
+
+/***********************************************************
+*
+* FUNCTIONS:	Peripheral Resource Allocation
+*		and PortMux Setup
+*
+* INPUTS/OUTPUTS:
+* per	Peripheral Identifier
+* label	String
+*
+* DESCRIPTION: Peripheral Resource Allocation and Setup API
+**************************************************************/
+
+int peripheral_request(unsigned short per, const char *label)
+{
+	unsigned short ident = P_IDENT(per);
+
+	/*
+	 * Don't cares are pins with only one dedicated function
+	 */
+
+	if (per & P_DONTCARE)
+		return 0;
+
+	if (!(per & P_DEFINED))
+		return -ENODEV;
+
+	BUG_ON(ident >= MAX_RESOURCES);
+
+	/* If a pin can be muxed as either GPIO or peripheral, make
+	 * sure it is not already a GPIO pin when we request it.
+	 */
+	if (unlikely(!check_gpio(ident) && is_reserved(gpio, ident, 1))) {
+		printf("%s: Peripheral %d is already reserved as GPIO by %s!\n",
+		       __func__, ident, get_label(ident));
+		return -EBUSY;
+	}
+
+	if (unlikely(is_reserved(peri, ident, 1))) {
+		/*
+		 * Pin functions like AMC address strobes my
+		 * be requested and used by several drivers
+		 */
+
+		if (!((per & P_MAYSHARE) &&
+			get_portmux(per) == P_FUNCT2MUX(per))) {
+			/*
+			 * Allow that the identical pin function can
+			 * be requested from the same driver twice
+			 */
+
+			if (cmp_label(ident, label) == 0)
+				goto anyway;
+
+			printf("%s: Peripheral %d function %d is already "
+				"reserved by %s!\n", __func__, ident,
+				P_FUNCT2MUX(per), get_label(ident));
+			return -EBUSY;
+		}
+	}
+
+ anyway:
+	reserve(peri, ident);
+
+	portmux_setup(per);
+	port_setup(ident, PERIPHERAL_USAGE);
+
+	set_label(ident, label);
+
+	return 0;
+}
+
+int peripheral_request_list(const unsigned short per[], const char *label)
+{
+	u16 cnt;
+	int ret;
+
+	for (cnt = 0; per[cnt] != 0; cnt++) {
+		ret = peripheral_request(per[cnt], label);
+
+		if (ret < 0) {
+			for (; cnt > 0; cnt--)
+				peripheral_free(per[cnt - 1]);
+
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+void peripheral_free(unsigned short per)
+{
+	unsigned short ident = P_IDENT(per);
+
+	if (per & P_DONTCARE)
+		return;
+
+	if (!(per & P_DEFINED))
+		return;
+
+	if (unlikely(!is_reserved(peri, ident, 0)))
+		return;
+
+	if (!(per & P_MAYSHARE))
+		port_setup(ident, GPIO_USAGE);
+
+	unreserve(peri, ident);
+
+	set_label(ident, "free");
+}
+
+void peripheral_free_list(const unsigned short per[])
+{
+	u16 cnt;
+	for (cnt = 0; per[cnt] != 0; cnt++)
+		peripheral_free(per[cnt]);
+}
+
+/***********************************************************
+*
+* FUNCTIONS: GPIO Driver
+*
+* INPUTS/OUTPUTS:
+* gpio	PIO Number between 0 and MAX_GPIOS
+* label	String
+*
+* DESCRIPTION: GPIO Driver API
+**************************************************************/
+
+int gpio_request(unsigned gpio, const char *label)
+{
+	if (check_gpio(gpio) < 0)
+		return -EINVAL;
+
+	/*
+	 * Allow that the identical GPIO can
+	 * be requested from the same driver twice
+	 * Do nothing and return -
+	 */
+
+	if (cmp_label(gpio, label) == 0)
+		return 0;
+
+	if (unlikely(is_reserved(gpio, gpio, 1))) {
+		printf("adi_gpio2: GPIO %d is already reserved by %s!\n",
+			gpio, get_label(gpio));
+		return -EBUSY;
+	}
+	if (unlikely(is_reserved(peri, gpio, 1))) {
+		printf("adi_gpio2: GPIO %d is already reserved as Peripheral "
+			"by %s!\n", gpio, get_label(gpio));
+		return -EBUSY;
+	}
+
+	reserve(gpio, gpio);
+	set_label(gpio, label);
+
+	port_setup(gpio, GPIO_USAGE);
+
+	return 0;
+}
+
+int gpio_free(unsigned gpio)
+{
+	if (check_gpio(gpio) < 0)
+		return -1;
+
+	if (unlikely(!is_reserved(gpio, gpio, 0))) {
+		gpio_error(gpio);
+		return -1;
+	}
+
+	unreserve(gpio, gpio);
+
+	set_label(gpio, "free");
+
+	return 0;
+}
+
+#ifdef ADI_SPECIAL_GPIO_BANKS
+static DECLARE_RESERVED_MAP(special_gpio, gpio_bank(MAX_RESOURCES));
+
+int special_gpio_request(unsigned gpio, const char *label)
+{
+	/*
+	 * Allow that the identical GPIO can
+	 * be requested from the same driver twice
+	 * Do nothing and return -
+	 */
+
+	if (cmp_label(gpio, label) == 0)
+		return 0;
+
+	if (unlikely(is_reserved(special_gpio, gpio, 1))) {
+		printf("adi_gpio2: GPIO %d is already reserved by %s!\n",
+			gpio, get_label(gpio));
+		return -EBUSY;
+	}
+	if (unlikely(is_reserved(peri, gpio, 1))) {
+		printf("adi_gpio2: GPIO %d is already reserved as Peripheral "
+			"by %s!\n", gpio, get_label(gpio));
+
+		return -EBUSY;
+	}
+
+	reserve(special_gpio, gpio);
+	reserve(peri, gpio);
+
+	set_label(gpio, label);
+	port_setup(gpio, GPIO_USAGE);
+
+	return 0;
+}
+
+void special_gpio_free(unsigned gpio)
+{
+	if (unlikely(!is_reserved(special_gpio, gpio, 0))) {
+		gpio_error(gpio);
+		return;
+	}
+
+	reserve(special_gpio, gpio);
+	reserve(peri, gpio);
+	set_label(gpio, "free");
+}
+#endif
+
+static inline void __gpio_direction_input(unsigned gpio)
+{
+	gpio_array[gpio_bank(gpio)]->dir_clear = gpio_bit(gpio);
+#if defined(CONFIG_BF54x)
+	gpio_array[gpio_bank(gpio)]->inen |= gpio_bit(gpio);
+#else
+	gpio_array[gpio_bank(gpio)]->inen_set = gpio_bit(gpio);
+#endif
+}
+
+int gpio_direction_input(unsigned gpio)
+{
+	unsigned long flags;
+
+	if (!is_reserved(gpio, gpio, 0)) {
+		gpio_error(gpio);
+		return -EINVAL;
+	}
+
+	local_irq_save(flags);
+	__gpio_direction_input(gpio);
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+int gpio_set_value(unsigned gpio, int arg)
+{
+	if (arg)
+		gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio);
+	else
+		gpio_array[gpio_bank(gpio)]->data_clear = gpio_bit(gpio);
+
+	return 0;
+}
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+	unsigned long flags;
+
+	if (!is_reserved(gpio, gpio, 0)) {
+		gpio_error(gpio);
+		return -EINVAL;
+	}
+
+	local_irq_save(flags);
+
+#if defined(CONFIG_BF54x)
+	gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio);
+#else
+	gpio_array[gpio_bank(gpio)]->inen_clear = gpio_bit(gpio);
+#endif
+	gpio_set_value(gpio, value);
+	gpio_array[gpio_bank(gpio)]->dir_set = gpio_bit(gpio);
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+int gpio_get_value(unsigned gpio)
+{
+	return 1 & (gpio_array[gpio_bank(gpio)]->data >> gpio_sub_n(gpio));
+}
+
+void gpio_labels(void)
+{
+	int c, gpio;
+
+	for (c = 0; c < MAX_RESOURCES; c++) {
+		gpio = is_reserved(gpio, c, 1);
+		if (!check_gpio(c) && gpio)
+			printf("GPIO_%d:\t%s\tGPIO %s\n", c, get_label(c),
+				get_gpio_dir(c) ? "OUTPUT" : "INPUT");
+		else if (is_reserved(peri, c, 1))
+			printf("GPIO_%d:\t%s\tPeripheral\n", c, get_label(c));
+		else
+			continue;
+	}
+}
diff --git a/include/configs/bf548-ezkit.h b/include/configs/bf548-ezkit.h
index 7ed0ea9..da5f029 100644
--- a/include/configs/bf548-ezkit.h
+++ b/include/configs/bf548-ezkit.h
@@ -182,6 +182,8 @@ 
 #define CONFIG_UART_CONSOLE	1
 #define CONFIG_BFIN_SPI_IMG_SIZE 0x50000
 
+#define CONFIG_ADI_GPIO2
+
 #undef CONFIG_VIDEO
 #ifdef CONFIG_VIDEO
 #define EASYLOGO_HEADER < asm/bfin_logo_230x230_gzip.h >
diff --git a/include/configs/bf609-ezkit.h b/include/configs/bf609-ezkit.h
index e7b02a5..1a43e1b 100644
--- a/include/configs/bf609-ezkit.h
+++ b/include/configs/bf609-ezkit.h
@@ -149,6 +149,8 @@ 
 #define CONFIG_SYS_MEMTEST_END (CONFIG_STACKBASE - 20*1024*1024 + 4)
 #define CONFIG_BFIN_SOFT_SWITCH
 
+#define CONFIG_ADI_GPIO2
+
 #if 0
 #define CONFIG_UART_MEM 1024
 #undef CONFIG_UART_CONSOLE
diff --git a/include/configs/bfin_adi_common.h b/include/configs/bfin_adi_common.h
index c751dd7..e1a6fe3 100644
--- a/include/configs/bfin_adi_common.h
+++ b/include/configs/bfin_adi_common.h
@@ -323,5 +323,7 @@ 
 #  define CONFIG_WATCHDOG_TIMEOUT_MSECS 5000
 # endif
 #endif
-
+#ifndef CONFIG_ADI_GPIO2
+# define CONFIG_ADI_GPIO1
+#endif
 #endif