[PATCH] GPIO: SAMSUNG: Consolidate GPIO library for SAMSUNG SoC

Chanwoo Choi cw00.choi at samsung.com
Mon Jul 4 06:28:27 EDT 2011


This patch consolidates duplicate GPIO library for SAMSUNG SoC
to control GPIO on the whole SAMSUNG SoC(S3C series, S5P series)
through consolidated GPIO library file.

Signed-off-by: Chanwoo Choi <cw00.choi at samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
---
 arch/arm/mach-s3c64xx/gpiolib.c                |   27 +---
 arch/arm/mach-s5p64x0/gpiolib.c                |    2 +-
 arch/arm/plat-s3c24xx/gpiolib.c                |    2 +-
 arch/arm/plat-samsung/Makefile                 |    1 -
 arch/arm/plat-samsung/gpio.c                   |  167 ----------------------
 arch/arm/plat-samsung/include/plat/gpio-core.h |   18 +--
 drivers/gpio/gpio-plat-samsung.c               |  182 +++++++++++++++++++++++-
 7 files changed, 183 insertions(+), 216 deletions(-)
 delete mode 100644 arch/arm/plat-samsung/gpio.c

diff --git a/arch/arm/mach-s3c64xx/gpiolib.c b/arch/arm/mach-s3c64xx/gpiolib.c
index 92b0908..75f32f6 100644
--- a/arch/arm/mach-s3c64xx/gpiolib.c
+++ b/arch/arm/mach-s3c64xx/gpiolib.c
@@ -257,32 +257,11 @@ static struct s3c_gpio_chip gpio_2bit[] = {
 	},
 };
 
-static __init void s3c64xx_gpiolib_add_2bit(struct s3c_gpio_chip *chip)
-{
-	chip->pm = __gpio_pm(&s3c_gpio_pm_2bit);
-}
-
-static __init void s3c64xx_gpiolib_add(struct s3c_gpio_chip *chips,
-				       int nr_chips,
-				       void (*fn)(struct s3c_gpio_chip *))
-{
-	for (; nr_chips > 0; nr_chips--, chips++) {
-		if (fn)
-			(fn)(chips);
-		s3c_gpiolib_add(chips);
-	}
-}
-
 static __init int s3c64xx_gpiolib_init(void)
 {
-	s3c64xx_gpiolib_add(gpio_4bit, ARRAY_SIZE(gpio_4bit),
-			    samsung_gpiolib_add_4bit);
-
-	s3c64xx_gpiolib_add(gpio_4bit2, ARRAY_SIZE(gpio_4bit2),
-			    samsung_gpiolib_add_4bit2);
-
-	s3c64xx_gpiolib_add(gpio_2bit, ARRAY_SIZE(gpio_2bit),
-			    s3c64xx_gpiolib_add_2bit);
+	samsung_gpiolib_add_4bit_chips(gpio_4bit, ARRAY_SIZE(gpio_4bit));
+	samsung_gpiolib_add_4bit2_chips(gpio_4bit2, ARRAY_SIZE(gpio_4bit2));
+	samsung_gpiolib_add_2bit_chips(gpio_2bit, ARRAY_SIZE(gpio_2bit));
 
 	return 0;
 }
diff --git a/arch/arm/mach-s5p64x0/gpiolib.c b/arch/arm/mach-s5p64x0/gpiolib.c
index e7fb3b0..a770735 100644
--- a/arch/arm/mach-s5p64x0/gpiolib.c
+++ b/arch/arm/mach-s5p64x0/gpiolib.c
@@ -467,7 +467,7 @@ static void __init s5p64x0_gpio_add_rbank_4bit2(struct s3c_gpio_chip *chip,
 		chip->chip.direction_input = s5p64x0_gpiolib_rbank_4bit2_input;
 		chip->chip.direction_output =
 					s5p64x0_gpiolib_rbank_4bit2_output;
-		s3c_gpiolib_add(chip);
+		samsung_gpiolib_add_chips(chip);
 	}
 }
 
diff --git a/arch/arm/plat-s3c24xx/gpiolib.c b/arch/arm/plat-s3c24xx/gpiolib.c
index 243b641..de2b4e2 100644
--- a/arch/arm/plat-s3c24xx/gpiolib.c
+++ b/arch/arm/plat-s3c24xx/gpiolib.c
@@ -220,7 +220,7 @@ static __init int s3c24xx_gpiolib_init(void)
 		if (!chip->config)
 			chip->config = &s3c24xx_gpiocfg_default;
 
-		s3c_gpiolib_add(chip);
+		samsung_gpiolib_add_2bit_chips(chip, ARRAY_SIZE(chip));
 	}
 
 	return 0;
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index 53eb15b..b9deba4 100644
--- a/arch/arm/plat-samsung/Makefile
+++ b/arch/arm/plat-samsung/Makefile
@@ -15,7 +15,6 @@ obj-y				+= init.o
 obj-$(CONFIG_ARCH_USES_GETTIMEOFFSET)   += time.o
 obj-y				+= clock.o
 obj-y				+= pwm-clock.o
-obj-y				+= gpio.o
 obj-y				+= gpio-config.o
 obj-y				+= dev-asocdma.o
 
diff --git a/arch/arm/plat-samsung/gpio.c b/arch/arm/plat-samsung/gpio.c
deleted file mode 100644
index 7743c4b..0000000
--- a/arch/arm/plat-samsung/gpio.c
+++ /dev/null
@@ -1,167 +0,0 @@
-/* linux/arch/arm/plat-s3c/gpio.c
- *
- * Copyright 2008 Simtec Electronics
- *	Ben Dooks <ben at simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C series GPIO core
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/spinlock.h>
-
-#include <plat/gpio-core.h>
-
-#ifdef CONFIG_S3C_GPIO_TRACK
-struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END];
-
-static __init void s3c_gpiolib_track(struct s3c_gpio_chip *chip)
-{
-	unsigned int gpn;
-	int i;
-
-	gpn = chip->chip.base;
-	for (i = 0; i < chip->chip.ngpio; i++, gpn++) {
-		BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios));
-		s3c_gpios[gpn] = chip;
-	}
-}
-#endif /* CONFIG_S3C_GPIO_TRACK */
-
-/* Default routines for controlling GPIO, based on the original S3C24XX
- * GPIO functions which deal with the case where each gpio bank of the
- * chip is as following:
- *
- * base + 0x00: Control register, 2 bits per gpio
- *	        gpio n: 2 bits starting at (2*n)
- *		00 = input, 01 = output, others mean special-function
- * base + 0x04: Data register, 1 bit per gpio
- *		bit n: data bit n
-*/
-
-static int s3c_gpiolib_input(struct gpio_chip *chip, unsigned offset)
-{
-	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-	void __iomem *base = ourchip->base;
-	unsigned long flags;
-	unsigned long con;
-
-	s3c_gpio_lock(ourchip, flags);
-
-	con = __raw_readl(base + 0x00);
-	con &= ~(3 << (offset * 2));
-
-	__raw_writel(con, base + 0x00);
-
-	s3c_gpio_unlock(ourchip, flags);
-	return 0;
-}
-
-static int s3c_gpiolib_output(struct gpio_chip *chip,
-			      unsigned offset, int value)
-{
-	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-	void __iomem *base = ourchip->base;
-	unsigned long flags;
-	unsigned long dat;
-	unsigned long con;
-
-	s3c_gpio_lock(ourchip, flags);
-
-	dat = __raw_readl(base + 0x04);
-	dat &= ~(1 << offset);
-	if (value)
-		dat |= 1 << offset;
-	__raw_writel(dat, base + 0x04);
-
-	con = __raw_readl(base + 0x00);
-	con &= ~(3 << (offset * 2));
-	con |= 1 << (offset * 2);
-
-	__raw_writel(con, base + 0x00);
-	__raw_writel(dat, base + 0x04);
-
-	s3c_gpio_unlock(ourchip, flags);
-	return 0;
-}
-
-static void s3c_gpiolib_set(struct gpio_chip *chip,
-			    unsigned offset, int value)
-{
-	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-	void __iomem *base = ourchip->base;
-	unsigned long flags;
-	unsigned long dat;
-
-	s3c_gpio_lock(ourchip, flags);
-
-	dat = __raw_readl(base + 0x04);
-	dat &= ~(1 << offset);
-	if (value)
-		dat |= 1 << offset;
-	__raw_writel(dat, base + 0x04);
-
-	s3c_gpio_unlock(ourchip, flags);
-}
-
-static int s3c_gpiolib_get(struct gpio_chip *chip, unsigned offset)
-{
-	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-	unsigned long val;
-
-	val = __raw_readl(ourchip->base + 0x04);
-	val >>= offset;
-	val &= 1;
-
-	return val;
-}
-
-__init void s3c_gpiolib_add(struct s3c_gpio_chip *chip)
-{
-	struct gpio_chip *gc = &chip->chip;
-	int ret;
-
-	BUG_ON(!chip->base);
-	BUG_ON(!gc->label);
-	BUG_ON(!gc->ngpio);
-
-	spin_lock_init(&chip->lock);
-
-	if (!gc->direction_input)
-		gc->direction_input = s3c_gpiolib_input;
-	if (!gc->direction_output)
-		gc->direction_output = s3c_gpiolib_output;
-	if (!gc->set)
-		gc->set = s3c_gpiolib_set;
-	if (!gc->get)
-		gc->get = s3c_gpiolib_get;
-
-#ifdef CONFIG_PM
-	if (chip->pm != NULL) {
-		if (!chip->pm->save || !chip->pm->resume)
-			printk(KERN_ERR "gpio: %s has missing PM functions\n",
-			       gc->label);
-	} else
-		printk(KERN_ERR "gpio: %s has no PM function\n", gc->label);
-#endif
-
-	/* gpiochip_add() prints own failure message on error. */
-	ret = gpiochip_add(gc);
-	if (ret >= 0)
-		s3c_gpiolib_track(chip);
-}
-
-int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
-{
-	struct s3c_gpio_chip *s3c_chip = container_of(chip,
-			struct s3c_gpio_chip, chip);
-
-	return s3c_chip->irq_base + offset;
-}
diff --git a/arch/arm/plat-samsung/include/plat/gpio-core.h b/arch/arm/plat-samsung/include/plat/gpio-core.h
index 8cad4cf..f76c3e3 100644
--- a/arch/arm/plat-samsung/include/plat/gpio-core.h
+++ b/arch/arm/plat-samsung/include/plat/gpio-core.h
@@ -78,16 +78,6 @@ static inline struct s3c_gpio_chip *to_s3c_gpio(struct gpio_chip *gpc)
 	return container_of(gpc, struct s3c_gpio_chip, chip);
 }
 
-/** s3c_gpiolib_add() - add the s3c specific version of a gpio_chip.
- * @chip: The chip to register
- *
- * This is a wrapper to gpiochip_add() that takes our specific gpio chip
- * information and makes the necessary alterations for the platform and
- * notes the information for use with the configuration systems and any
- * other parts of the system.
- */
-extern void s3c_gpiolib_add(struct s3c_gpio_chip *chip);
-
 /* CONFIG_S3C_GPIO_TRACK enables the tracking of the s3c specific gpios
  * for use with the configuration calls, and other parts of the s3c gpiolib
  * support code.
@@ -120,10 +110,8 @@ extern void samsung_gpiolib_add_4bit2_chips(struct s3c_gpio_chip *chip,
 					    int nr_chips);
 extern void samsung_gpiolib_add_2bit_chips(struct s3c_gpio_chip *chip,
 					   int nr_chips);
-
-extern void samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip);
-extern void samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip);
-
+extern void samsung_gpiolib_add_chips(struct s3c_gpio_chip *chip,
+					   int nr_chips);
 
 /**
  * samsung_gpiolib_to_irq - convert gpio pin to irq number
@@ -150,7 +138,7 @@ static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int chip)
 
 #include <mach/gpio-track.h>
 
-static inline void s3c_gpiolib_track(struct s3c_gpio_chip *chip) { }
+static inline void samsung_gpiolib_track(struct s3c_gpio_chip *chip) { }
 #endif
 
 #ifdef CONFIG_PM
diff --git a/drivers/gpio/gpio-plat-samsung.c b/drivers/gpio/gpio-plat-samsung.c
index ea37c04..a2fc6f3 100644
--- a/drivers/gpio/gpio-plat-samsung.c
+++ b/drivers/gpio/gpio-plat-samsung.c
@@ -7,6 +7,9 @@
  *
  * Copyright (c) 2009 Samsung Electronics Co., Ltd.
  *		http://www.samsung.com/
+ 
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
  *
  * SAMSUNG - GPIOlib support
  *
@@ -29,6 +32,63 @@
 #define gpio_dbg(x...) printk(KERN_DEBUG x)
 #endif
 
+/* Default routines for controlling GPIO, based on the original S3C24XX
+ * GPIO functions which deal with the case where each gpio bank of the
+ * chip is as following:
+ *
+ * base + 0x00: Control register, 2 bits per gpio
+ *	        gpio n: 2 bits starting at (2*n)
+ *		00 = input, 01 = output, others mean special-function
+ * base + 0x04: Data register, 1 bit per gpio
+ *		bit n: data bit n
+*/
+
+static int samsung_gpiolib_2bit_input(struct gpio_chip *chip, unsigned offset)
+{
+	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
+	void __iomem *base = ourchip->base;
+	unsigned long flags;
+	unsigned long con;
+
+	s3c_gpio_lock(ourchip, flags);
+
+	con = __raw_readl(base + GPIOCON_OFF);
+	con &= ~(3 << (offset * 2));
+
+	__raw_writel(con, base + GPIOCON_OFF);
+
+	s3c_gpio_unlock(ourchip, flags);
+	return 0;
+}
+
+static int samsung_gpiolib_2bit_output(struct gpio_chip *chip,
+			      unsigned offset, int value)
+{
+	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
+	void __iomem *base = ourchip->base;
+	unsigned long flags;
+	unsigned long dat;
+	unsigned long con;
+
+	s3c_gpio_lock(ourchip, flags);
+
+	dat = __raw_readl(base + GPIODAT_OFF);
+	dat &= ~(1 << offset);
+	if (value)
+		dat |= 1 << offset;
+	__raw_writel(dat, base + GPIODAT_OFF);
+
+	con = __raw_readl(base + GPIOCON_OFF);
+	con &= ~(3 << (offset * 2));
+	con |= 1 << (offset * 2);
+
+	__raw_writel(con, base + GPIOCON_OFF);
+	__raw_writel(dat, base + GPIODAT_OFF);
+
+	s3c_gpio_unlock(ourchip, flags);
+	return 0;
+}
+
 /* The samsung_gpiolib_4bit routines are to control the gpio banks where
  * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
  * following example:
@@ -166,26 +226,134 @@ static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
 	return 0;
 }
 
-void __init samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip)
+static void samsung_gpiolib_set(struct gpio_chip *chip,
+			    unsigned offset, int value)
+{
+	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
+	void __iomem *base = ourchip->base;
+	unsigned long flags;
+	unsigned long dat;
+
+	s3c_gpio_lock(ourchip, flags);
+
+	dat = __raw_readl(base + 0x04);
+	dat &= ~(1 << offset);
+	if (value)
+		dat |= 1 << offset;
+	__raw_writel(dat, base + 0x04);
+
+	s3c_gpio_unlock(ourchip, flags);
+}
+
+static int samsung_gpiolib_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
+	unsigned long val;
+
+	val = __raw_readl(ourchip->base + 0x04);
+	val >>= offset;
+	val &= 1;
+
+	return val;
+}
+
+#ifdef CONFIG_S3C_GPIO_TRACK
+struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END];
+
+static __init void samsung_gpiolib_track(struct s3c_gpio_chip *chip)
+{
+	unsigned int gpn;
+	int i;
+
+	gpn = chip->chip.base;
+	for (i = 0; i < chip->chip.ngpio; i++, gpn++) {
+		BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios));
+		s3c_gpios[gpn] = chip;
+	}
+}
+#endif
+
+static void samsung_gpiolib_add_2bit(struct s3c_gpio_chip *chip)
+{
+	chip->chip.direction_input = samsung_gpiolib_2bit_input;
+	chip->chip.direction_output = samsung_gpiolib_2bit_output;
+
+#ifdef CONFIG_ARCH_S3C64XX
+	chip->pm = __gpio_pm(&s3c_gpio_pm_2bit);
+#endif
+}
+
+static void samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip)
 {
 	chip->chip.direction_input = samsung_gpiolib_4bit_input;
 	chip->chip.direction_output = samsung_gpiolib_4bit_output;
 	chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
 }
 
-void __init samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip)
+static void samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip)
 {
 	chip->chip.direction_input = samsung_gpiolib_4bit2_input;
 	chip->chip.direction_output = samsung_gpiolib_4bit2_output;
 	chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
 }
 
+static void samsung_gpiolib_add(struct s3c_gpio_chip *chip)
+{
+	struct gpio_chip *gc = &chip->chip;
+	int ret;
+
+	BUG_ON(!chip->base);
+	BUG_ON(!gc->label);
+	BUG_ON(!gc->ngpio);
+
+	spin_lock_init(&chip->lock);
+
+	if (!gc->direction_input)
+		gc->direction_input = samsung_gpiolib_2bit_input;
+	if (!gc->direction_output)
+		gc->direction_output = samsung_gpiolib_2bit_output;
+	if (!gc->set)
+		gc->set = samsung_gpiolib_set;
+	if (!gc->get)
+		gc->get = samsung_gpiolib_get;
+
+#ifdef CONFIG_PM
+	if (chip->pm != NULL) {
+		if (!chip->pm->save || !chip->pm->resume)
+			printk(KERN_ERR "gpio: %s has missing PM functions\n",
+			       gc->label);
+	} else
+		printk(KERN_ERR "gpio: %s has no PM function\n", gc->label);
+#endif
+
+	/* gpiochip_add() prints own failure message on error. */
+	ret = gpiochip_add(gc);
+	if (ret >= 0)
+		samsung_gpiolib_track(chip);
+}
+
+int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
+{
+	struct s3c_gpio_chip *s3c_chip = container_of(chip,
+			struct s3c_gpio_chip, chip);
+	return s3c_chip->irq_base + offset;
+}
+
+void __init samsung_gpiolib_add_2bit_chips(struct s3c_gpio_chip *chip,
+					   int nr_chips)
+{
+	for (; nr_chips > 0; nr_chips--, chip++) {
+		samsung_gpiolib_add_2bit(chip);
+		samsung_gpiolib_add(chip);
+	}
+}
+
 void __init samsung_gpiolib_add_4bit_chips(struct s3c_gpio_chip *chip,
 					   int nr_chips)
 {
 	for (; nr_chips > 0; nr_chips--, chip++) {
 		samsung_gpiolib_add_4bit(chip);
-		s3c_gpiolib_add(chip);
+		samsung_gpiolib_add(chip);
 	}
 }
 
@@ -194,13 +362,13 @@ void __init samsung_gpiolib_add_4bit2_chips(struct s3c_gpio_chip *chip,
 {
 	for (; nr_chips > 0; nr_chips--, chip++) {
 		samsung_gpiolib_add_4bit2(chip);
-		s3c_gpiolib_add(chip);
+		samsung_gpiolib_add(chip);
 	}
 }
 
-void __init samsung_gpiolib_add_2bit_chips(struct s3c_gpio_chip *chip,
-					   int nr_chips)
+void __init samsung_gpiolib_add_chips(struct s3c_gpio_chip *chip,
+					    int nr_chips)
 {
 	for (; nr_chips > 0; nr_chips--, chip++)
-		s3c_gpiolib_add(chip);
+		samsung_gpiolib_add(chip);
 }



More information about the linux-arm-kernel mailing list