Explorar o código

ARM: Merge for-2635/gpio2

Merge branch 'for-2635/gpio2' into for-linus/samsung2
Ben Dooks %!s(int64=15) %!d(string=hai) anos
pai
achega
ff1b8ba01d
Modificáronse 40 ficheiros con 531 adicións e 342 borrados
  1. 1 0
      arch/arm/mach-s3c2410/Kconfig
  2. 20 12
      arch/arm/mach-s3c2410/h1940-bluetooth.c
  3. 24 23
      arch/arm/mach-s3c2410/include/mach/gpio-fns.h
  4. 31 6
      arch/arm/mach-s3c2410/include/mach/gpio-nrs.h
  5. 2 2
      arch/arm/mach-s3c2410/include/mach/gpio-track.h
  6. 8 0
      arch/arm/mach-s3c2410/include/mach/gpio.h
  7. 19 20
      arch/arm/mach-s3c2410/include/mach/regs-gpio.h
  8. 0 36
      arch/arm/mach-s3c2410/include/mach/regs-gpioj.h
  9. 3 2
      arch/arm/mach-s3c2410/mach-amlm5900.c
  10. 5 4
      arch/arm/mach-s3c2410/mach-bast.c
  11. 11 9
      arch/arm/mach-s3c2410/mach-h1940.c
  12. 3 0
      arch/arm/mach-s3c2410/mach-n30.c
  13. 6 4
      arch/arm/mach-s3c2410/mach-qt2410.c
  14. 3 2
      arch/arm/mach-s3c2410/mach-vr1000.c
  15. 8 0
      arch/arm/mach-s3c2410/s3c2410.c
  16. 11 9
      arch/arm/mach-s3c2412/gpio.c
  17. 13 13
      arch/arm/mach-s3c2412/mach-jive.c
  18. 4 4
      arch/arm/mach-s3c2412/mach-smdk2413.c
  19. 1 0
      arch/arm/mach-s3c2440/Kconfig
  20. 12 11
      arch/arm/mach-s3c2440/mach-mini2440.c
  21. 5 4
      arch/arm/mach-s3c2440/mach-nexcoder.c
  22. 3 2
      arch/arm/mach-s3c2440/mach-osiris.c
  23. 8 0
      arch/arm/mach-s3c2440/s3c2440.c
  24. 6 0
      arch/arm/mach-s3c64xx/gpiolib.c
  25. 5 0
      arch/arm/mach-s5p6440/gpio.c
  26. 1 0
      arch/arm/plat-s3c24xx/Kconfig
  27. 5 4
      arch/arm/plat-s3c24xx/common-smdk.c
  28. 22 128
      arch/arm/plat-s3c24xx/gpio.c
  29. 58 2
      arch/arm/plat-s3c24xx/gpiolib.c
  30. 5 4
      arch/arm/plat-s3c24xx/pm.c
  31. 3 2
      arch/arm/plat-s3c24xx/setup-i2c.c
  32. 8 8
      arch/arm/plat-s3c24xx/spi-bus0-gpe11_12_13.c
  33. 8 8
      arch/arm/plat-s3c24xx/spi-bus1-gpd8_9_10.c
  34. 8 8
      arch/arm/plat-s3c24xx/spi-bus1-gpg5_6_7.c
  35. 104 7
      arch/arm/plat-samsung/gpio-config.c
  36. 9 6
      arch/arm/plat-samsung/gpio.c
  37. 58 0
      arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h
  38. 11 0
      arch/arm/plat-samsung/include/plat/gpio-cfg.h
  39. 17 0
      arch/arm/plat-samsung/include/plat/gpio-core.h
  40. 2 2
      arch/arm/plat-samsung/pm-gpio.c

+ 1 - 0
arch/arm/mach-s3c2410/Kconfig

@@ -6,6 +6,7 @@ config CPU_S3C2410
 	bool
 	depends on ARCH_S3C2410
 	select CPU_ARM920T
+	select S3C_GPIO_PULL_UP
 	select S3C2410_CLOCK
 	select S3C2410_GPIO
 	select CPU_LLSERIAL_S3C2410

+ 20 - 12
arch/arm/mach-s3c2410/h1940-bluetooth.c

@@ -33,14 +33,15 @@ static void h1940bt_enable(int on)
 		h1940_latch_control(0, H1940_LATCH_BLUETOOTH_POWER);
 		/* Reset the chip */
 		mdelay(10);
-		s3c2410_gpio_setpin(S3C2410_GPH(1), 1);
+
+		gpio_set_value(S3C2410_GPH(1), 1);
 		mdelay(10);
-		s3c2410_gpio_setpin(S3C2410_GPH(1), 0);
+		gpio_set_value(S3C2410_GPH(1), 0);
 	}
 	else {
-		s3c2410_gpio_setpin(S3C2410_GPH(1), 1);
+		gpio_set_value(S3C2410_GPH(1), 1);
 		mdelay(10);
-		s3c2410_gpio_setpin(S3C2410_GPH(1), 0);
+		gpio_set_value(S3C2410_GPH(1), 0);
 		mdelay(10);
 		h1940_latch_control(H1940_LATCH_BLUETOOTH_POWER, 0);
 	}
@@ -61,15 +62,21 @@ static int __devinit h1940bt_probe(struct platform_device *pdev)
 	struct rfkill *rfk;
 	int ret = 0;
 
+	ret = gpio_request(S3C2410_GPH(1), dev_name(&pdev->dev));
+	if (ret) {
+		dev_err(&pdev->dev, "could not get GPH1\n");\
+		return ret;
+	}
+
 	/* Configures BT serial port GPIOs */
-	s3c2410_gpio_cfgpin(S3C2410_GPH(0), S3C2410_GPH0_nCTS0);
-	s3c2410_gpio_pullup(S3C2410_GPH(0), 1);
-	s3c2410_gpio_cfgpin(S3C2410_GPH(1), S3C2410_GPIO_OUTPUT);
-	s3c2410_gpio_pullup(S3C2410_GPH(1), 1);
-	s3c2410_gpio_cfgpin(S3C2410_GPH(2), S3C2410_GPH2_TXD0);
-	s3c2410_gpio_pullup(S3C2410_GPH(2), 1);
-	s3c2410_gpio_cfgpin(S3C2410_GPH(3), S3C2410_GPH3_RXD0);
-	s3c2410_gpio_pullup(S3C2410_GPH(3), 1);
+	s3c_gpio_cfgpin(S3C2410_GPH(0), S3C2410_GPH0_nCTS0);
+	s3c_gpio_cfgpull(S3C2410_GPH(0), S3C_GPIO_PULL_NONE);
+	s3c_gpio_cfgpin(S3C2410_GPH(1), S3C2410_GPIO_OUTPUT);
+	s3c_gpio_cfgpull(S3C2410_GPH(1), S3C_GPIO_PULL_NONE);
+	s3c_gpio_cfgpin(S3C2410_GPH(2), S3C2410_GPH2_TXD0);
+	s3c_gpio_cfgpull(S3C2410_GPH(2), S3C_GPIO_PULL_NONE);
+	s3c_gpio_cfgpin(S3C2410_GPH(3), S3C2410_GPH3_RXD0);
+	s3c_gpio_cfgpull(S3C2410_GPH(3), S3C_GPIO_PULL_NONE);
 
 
 	rfk = rfkill_alloc(DRV_NAME, &pdev->dev, RFKILL_TYPE_BLUETOOTH,
@@ -100,6 +107,7 @@ static int h1940bt_remove(struct platform_device *pdev)
 	struct rfkill *rfk = platform_get_drvdata(pdev);
 
 	platform_set_drvdata(pdev, NULL);
+	gpio_free(S3C2410_GPH(1));
 
 	if (rfk) {
 		rfkill_unregister(rfk);

+ 24 - 23
arch/arm/mach-s3c2410/include/mach/gpio-fns.h

@@ -10,14 +10,28 @@
  * published by the Free Software Foundation.
 */
 
+#ifndef __MACH_GPIO_FNS_H
+#define __MACH_GPIO_FNS_H __FILE__
+
 /* These functions are in the to-be-removed category and it is strongly
  * encouraged not to use these in new code. They will be marked deprecated
  * very soon.
  *
  * Most of the functionality can be either replaced by the gpiocfg calls
  * for the s3c platform or by the generic GPIOlib API.
+ *
+ * As of 2.6.35-rc, these will be removed, with the few drivers using them
+ * either replaced or given a wrapper until the calls can be removed.
 */
 
+#include <plat/gpio-cfg.h>
+
+static inline void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int cfg)
+{
+	/* 1:1 mapping between cfgpin and setcfg calls at the moment */
+	s3c_gpio_cfgpin(pin, cfg);
+}
+
 /* external functions for GPIO support
  *
  * These allow various different clients to access the same GPIO
@@ -25,17 +39,6 @@
  * GPIO register, then it is safe to ioremap/__raw_{read|write} to it.
 */
 
-/* s3c2410_gpio_cfgpin
- *
- * set the configuration of the given pin to the value passed.
- *
- * eg:
- *    s3c2410_gpio_cfgpin(S3C2410_GPA(0), S3C2410_GPA0_ADDR0);
- *    s3c2410_gpio_cfgpin(S3C2410_GPE(8), S3C2410_GPE8_SDDAT1);
-*/
-
-extern void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function);
-
 extern unsigned int s3c2410_gpio_getcfg(unsigned int pin);
 
 /* s3c2410_gpio_getirq
@@ -71,6 +74,14 @@ extern int s3c2400_gpio_getirq(unsigned int pin);
 extern int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
 				  unsigned int config);
 
+/* s3c2410_gpio_pullup
+ *
+ * This call should be replaced with s3c_gpio_setpull().
+ *
+ * As a note, there is currently no distinction between pull-up and pull-down
+ * in the s3c24xx series devices with only an on/off configuration.
+ */
+
 /* s3c2410_gpio_pullup
  *
  * configure the pull-up control on the given pin
@@ -86,18 +97,8 @@ extern int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
 
 extern void s3c2410_gpio_pullup(unsigned int pin, unsigned int to);
 
-/* s3c2410_gpio_getpull
- *
- * Read the state of the pull-up on a given pin
- *
- * return:
- *	< 0 => error code
- *	  0 => enabled
- *	  1 => disabled
-*/
-
-extern int s3c2410_gpio_getpull(unsigned int pin);
-
 extern void s3c2410_gpio_setpin(unsigned int pin, unsigned int to);
 
 extern unsigned int s3c2410_gpio_getpin(unsigned int pin);
+
+#endif /* __MACH_GPIO_FNS_H */

+ 31 - 6
arch/arm/mach-s3c2410/include/mach/gpio-nrs.h

@@ -16,15 +16,28 @@
 
 #define S3C2410_GPIONO(bank,offset) ((bank) + (offset))
 
-#define S3C2410_GPIO_BANKA   (32*0)
-#define S3C2410_GPIO_BANKB   (32*1)
-#define S3C2410_GPIO_BANKC   (32*2)
-#define S3C2410_GPIO_BANKD   (32*3)
-#define S3C2410_GPIO_BANKE   (32*4)
-#define S3C2410_GPIO_BANKF   (32*5)
 #define S3C2410_GPIO_BANKG   (32*6)
 #define S3C2410_GPIO_BANKH   (32*7)
 
+/* GPIO sizes for various SoCs:
+ *
+ *             2442
+ *   2410 2412 2440 2443 2416
+ *   ---- ---- ---- ---- ----
+ * A 23   22   25   16   25
+ * B 11   11   11   11   9
+ * C 16   15   16   16   16
+ * D 16   16   16   16   16
+ * E 16   16   16   16   16
+ * F 8    8    8    8    8
+ * G 16   16   16   16   8
+ * H 11   11   9    15   15
+ * J --   --   13   16   --
+ * K --   --   --   --   16
+ * L --   --   --   15   7
+ * M --   --   --   2    2
+ */
+
 /* GPIO bank sizes */
 #define S3C2410_GPIO_A_NR	(32)
 #define S3C2410_GPIO_B_NR	(32)
@@ -34,6 +47,10 @@
 #define S3C2410_GPIO_F_NR	(32)
 #define S3C2410_GPIO_G_NR	(32)
 #define S3C2410_GPIO_H_NR	(32)
+#define S3C2410_GPIO_J_NR	(32)	/* technically 16. */
+#define S3C2410_GPIO_K_NR	(32)	/* technically 16. */
+#define S3C2410_GPIO_L_NR	(32)	/* technically 15. */
+#define S3C2410_GPIO_M_NR	(32)	/* technically 2. */
 
 #if CONFIG_S3C_GPIO_SPACE != 0
 #error CONFIG_S3C_GPIO_SPACE cannot be zero at the moment
@@ -53,6 +70,10 @@ enum s3c_gpio_number {
 	S3C2410_GPIO_F_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_E),
 	S3C2410_GPIO_G_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_F),
 	S3C2410_GPIO_H_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_G),
+	S3C2410_GPIO_J_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_H),
+	S3C2410_GPIO_K_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_J),
+	S3C2410_GPIO_L_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_K),
+	S3C2410_GPIO_M_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_L),
 };
 
 #endif /* __ASSEMBLY__ */
@@ -67,6 +88,10 @@ enum s3c_gpio_number {
 #define S3C2410_GPF(_nr)	(S3C2410_GPIO_F_START + (_nr))
 #define S3C2410_GPG(_nr)	(S3C2410_GPIO_G_START + (_nr))
 #define S3C2410_GPH(_nr)	(S3C2410_GPIO_H_START + (_nr))
+#define S3C2410_GPJ(_nr)	(S3C2410_GPIO_J_START + (_nr))
+#define S3C2410_GPK(_nr)	(S3C2410_GPIO_K_START + (_nr))
+#define S3C2410_GPL(_nr)	(S3C2410_GPIO_L_START + (_nr))
+#define S3C2410_GPM(_nr)	(S3C2410_GPIO_M_START + (_nr))
 
 /* compatibility until drivers can be modified */
 

+ 2 - 2
arch/arm/mach-s3c2410/include/mach/gpio-track.h

@@ -23,11 +23,11 @@ static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int pin)
 {
 	struct s3c_gpio_chip *chip;
 
-	if (pin > S3C2410_GPG(10))
+	if (pin > S3C_GPIO_END)
 		return NULL;
 
 	chip = &s3c24xx_gpios[pin/32];
-	return (S3C2410_GPIO_OFFSET(pin) < chip->chip.ngpio) ? chip : NULL;
+	return ((pin - chip->chip.base) < chip->chip.ngpio) ? chip : NULL;
 }
 
 #endif /* __ASM_ARCH_GPIO_CORE_H */

+ 8 - 0
arch/arm/mach-s3c2410/include/mach/gpio.h

@@ -20,10 +20,18 @@
  * devices that need GPIO.
  */
 
+#ifdef CONFIG_CPU_S3C244X
+#define ARCH_NR_GPIOS	(32 * 9 + CONFIG_S3C24XX_GPIO_EXTRA)
+#else
 #define ARCH_NR_GPIOS	(256 + CONFIG_S3C24XX_GPIO_EXTRA)
+#endif
 
 #include <asm-generic/gpio.h>
 #include <mach/gpio-nrs.h>
 #include <mach/gpio-fns.h>
 
+#ifdef CONFIG_CPU_S3C24XX
+#define S3C_GPIO_END	(S3C2410_GPIO_BANKJ + 32)
+#else
 #define S3C_GPIO_END	(S3C2410_GPIO_BANKH + 32)
+#endif

+ 19 - 20
arch/arm/mach-s3c2410/include/mach/regs-gpio.h

@@ -17,29 +17,11 @@
 #include <mach/gpio-nrs.h>
 
 #ifdef CONFIG_CPU_S3C2400
-#define S3C24XX_GPIO_BASE(x)  S3C2400_GPIO_BASE(x)
-#define S3C24XX_MISCCR        S3C2400_MISCCR
+#define S3C24XX_MISCCR		S3C2400_MISCCR
 #else
-#define S3C24XX_GPIO_BASE(x)  S3C2410_GPIO_BASE(x)
-#define S3C24XX_MISCCR	      S3C24XX_GPIOREG2(0x80)
+#define S3C24XX_MISCCR		S3C24XX_GPIOREG2(0x80)
 #endif /* CONFIG_CPU_S3C2400 */
 
-
-/* S3C2400 doesn't have a 1:1 mapping to S3C2410 gpio base pins */
-
-#define S3C2400_BANKNUM(pin)     (((pin) & ~31) / 32)
-#define S3C2400_BASEA2B(pin)     ((((pin) & ~31) >> 2))
-#define S3C2400_BASEC2H(pin)     ((S3C2400_BANKNUM(pin) * 10) + \
-                                 (2 * (S3C2400_BANKNUM(pin)-2)))
-
-#define S3C2400_GPIO_BASE(pin)   (pin < S3C2410_GPIO_BANKC ? \
-                                 S3C2400_BASEA2B(pin)+S3C24XX_VA_GPIO : \
-                                 S3C2400_BASEC2H(pin)+S3C24XX_VA_GPIO)
-
-
-#define S3C2410_GPIO_BASE(pin)   ((((pin) & ~31) >> 1) + S3C24XX_VA_GPIO)
-#define S3C2410_GPIO_OFFSET(pin) ((pin) & 31)
-
 /* general configuration options */
 
 #define S3C2410_GPIO_LEAVE   (0xFFFFFFFF)
@@ -639,6 +621,23 @@
  * for the 2412/2413 from the 2410/2440/2442
 */
 
+/* S3C2443 and above */
+#define S3C2440_GPJCON	   S3C2410_GPIOREG(0xD0)
+#define S3C2440_GPJDAT	   S3C2410_GPIOREG(0xD4)
+#define S3C2440_GPJUP	   S3C2410_GPIOREG(0xD8)
+
+#define S3C2443_GPKCON	   S3C2410_GPIOREG(0xE0)
+#define S3C2443_GPKDAT	   S3C2410_GPIOREG(0xE4)
+#define S3C2443_GPKUP	   S3C2410_GPIOREG(0xE8)
+
+#define S3C2443_GPLCON	   S3C2410_GPIOREG(0xF0)
+#define S3C2443_GPLDAT	   S3C2410_GPIOREG(0xF4)
+#define S3C2443_GPLUP	   S3C2410_GPIOREG(0xF8)
+
+#define S3C2443_GPMCON	   S3C2410_GPIOREG(0x100)
+#define S3C2443_GPMDAT	   S3C2410_GPIOREG(0x104)
+#define S3C2443_GPMUP	   S3C2410_GPIOREG(0x108)
+
 /* miscellaneous control */
 #define S3C2400_MISCCR	   S3C2410_GPIOREG(0x54)
 #define S3C2410_MISCCR	   S3C2410_GPIOREG(0x80)

+ 0 - 36
arch/arm/mach-s3c2410/include/mach/regs-gpioj.h

@@ -22,85 +22,49 @@
  * pull up works like all other ports.
 */
 
-#define S3C2440_GPIO_BANKJ  (416)
-
-#define S3C2440_GPJCON	    S3C2410_GPIOREG(0xd0)
-#define S3C2440_GPJDAT	    S3C2410_GPIOREG(0xd4)
-#define S3C2440_GPJUP	    S3C2410_GPIOREG(0xd8)
-
 #define S3C2413_GPJCON		S3C2410_GPIOREG(0x80)
 #define S3C2413_GPJDAT		S3C2410_GPIOREG(0x84)
 #define S3C2413_GPJUP		S3C2410_GPIOREG(0x88)
 #define S3C2413_GPJSLPCON	S3C2410_GPIOREG(0x8C)
 
-#define S3C2440_GPJ0            S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 0)
-#define S3C2440_GPJ0_INP        (0x00 << 0)
 #define S3C2440_GPJ0_OUTP       (0x01 << 0)
 #define S3C2440_GPJ0_CAMDATA0   (0x02 << 0)
 
-#define S3C2440_GPJ1            S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 1)
-#define S3C2440_GPJ1_INP        (0x00 << 2)
 #define S3C2440_GPJ1_OUTP       (0x01 << 2)
 #define S3C2440_GPJ1_CAMDATA1   (0x02 << 2)
 
-#define S3C2440_GPJ2            S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 2)
-#define S3C2440_GPJ2_INP        (0x00 << 4)
 #define S3C2440_GPJ2_OUTP       (0x01 << 4)
 #define S3C2440_GPJ2_CAMDATA2   (0x02 << 4)
 
-#define S3C2440_GPJ3            S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 3)
-#define S3C2440_GPJ3_INP        (0x00 << 6)
 #define S3C2440_GPJ3_OUTP       (0x01 << 6)
 #define S3C2440_GPJ3_CAMDATA3   (0x02 << 6)
 
-#define S3C2440_GPJ4            S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 4)
-#define S3C2440_GPJ4_INP        (0x00 << 8)
 #define S3C2440_GPJ4_OUTP       (0x01 << 8)
 #define S3C2440_GPJ4_CAMDATA4   (0x02 << 8)
 
-#define S3C2440_GPJ5            S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 5)
-#define S3C2440_GPJ5_INP        (0x00 << 10)
 #define S3C2440_GPJ5_OUTP       (0x01 << 10)
 #define S3C2440_GPJ5_CAMDATA5   (0x02 << 10)
 
-#define S3C2440_GPJ6            S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 6)
-#define S3C2440_GPJ6_INP        (0x00 << 12)
 #define S3C2440_GPJ6_OUTP       (0x01 << 12)
 #define S3C2440_GPJ6_CAMDATA6   (0x02 << 12)
 
-#define S3C2440_GPJ7            S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 7)
-#define S3C2440_GPJ7_INP        (0x00 << 14)
 #define S3C2440_GPJ7_OUTP       (0x01 << 14)
 #define S3C2440_GPJ7_CAMDATA7   (0x02 << 14)
 
-#define S3C2440_GPJ8            S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 8)
-#define S3C2440_GPJ8_INP        (0x00 << 16)
 #define S3C2440_GPJ8_OUTP       (0x01 << 16)
 #define S3C2440_GPJ8_CAMPCLK    (0x02 << 16)
 
-#define S3C2440_GPJ9            S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 9)
-#define S3C2440_GPJ9_INP        (0x00 << 18)
 #define S3C2440_GPJ9_OUTP       (0x01 << 18)
 #define S3C2440_GPJ9_CAMVSYNC   (0x02 << 18)
 
-#define S3C2440_GPJ10           S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 10)
-#define S3C2440_GPJ10_INP       (0x00 << 20)
 #define S3C2440_GPJ10_OUTP      (0x01 << 20)
 #define S3C2440_GPJ10_CAMHREF   (0x02 << 20)
 
-#define S3C2440_GPJ11           S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 11)
-#define S3C2440_GPJ11_INP       (0x00 << 22)
 #define S3C2440_GPJ11_OUTP      (0x01 << 22)
 #define S3C2440_GPJ11_CAMCLKOUT (0x02 << 22)
 
-#define S3C2440_GPJ12           S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 12)
-#define S3C2440_GPJ12_INP       (0x00 << 24)
 #define S3C2440_GPJ12_OUTP      (0x01 << 24)
 #define S3C2440_GPJ12_CAMRESET  (0x02 << 24)
 
-#define S3C2443_GPJ13		S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 13)
-#define S3C2443_GPJ14		S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 14)
-#define S3C2443_GPJ15		S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 15)
-
 #endif	/* __ASM_ARCH_REGS_GPIOJ_H */
 

+ 3 - 2
arch/arm/mach-s3c2410/mach-amlm5900.c

@@ -56,6 +56,7 @@
 #include <plat/iic.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
+#include <plat/gpio-cfg.h>
 
 #ifdef CONFIG_MTD_PARTITIONS
 
@@ -225,8 +226,8 @@ static void amlm5900_init_pm(void)
 	} else {
 		enable_irq_wake(IRQ_EINT9);
 		/* configure the suspend/resume status pin */
-		s3c2410_gpio_cfgpin(S3C2410_GPF(2), S3C2410_GPIO_OUTPUT);
-		s3c2410_gpio_pullup(S3C2410_GPF(2), 0);
+		s3c_gpio_cfgpin(S3C2410_GPF(2), S3C2410_GPIO_OUTPUT);
+		s3c_gpio_setpull(S3C2410_GPF(2), S3C_GPIO_PULL_UP);
 	}
 }
 static void __init amlm5900_init(void)

+ 5 - 4
arch/arm/mach-s3c2410/mach-bast.c

@@ -61,6 +61,7 @@
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/cpu-freq.h>
+#include <plat/gpio-cfg.h>
 #include <plat/audio-simtec.h>
 
 #include "usb-simtec.h"
@@ -216,15 +217,13 @@ static struct s3c2410_uartcfg bast_uartcfgs[] __initdata = {
 static int bast_pm_suspend(struct sys_device *sd, pm_message_t state)
 {
 	/* ensure that an nRESET is not generated on resume. */
-	s3c2410_gpio_setpin(S3C2410_GPA(21), 1);
-	s3c2410_gpio_cfgpin(S3C2410_GPA(21), S3C2410_GPIO_OUTPUT);
-
+	gpio_direction_output(S3C2410_GPA(21), 1);
 	return 0;
 }
 
 static int bast_pm_resume(struct sys_device *sd)
 {
-	s3c2410_gpio_cfgpin(S3C2410_GPA(21), S3C2410_GPA21_nRSTOUT);
+	s3c_gpio_cfgpin(S3C2410_GPA(21), S3C2410_GPA21_nRSTOUT);
 	return 0;
 }
 
@@ -658,6 +657,8 @@ static void __init bast_init(void)
 	nor_simtec_init();
 	simtec_audio_add(NULL, true, &bast_audio);
 
+	WARN_ON(gpio_request(S3C2410_GPA(21), "bast nreset"));
+	
 	s3c_cpufreq_setboard(&bast_cpufreq);
 }
 

+ 11 - 9
arch/arm/mach-s3c2410/mach-h1940.c

@@ -50,6 +50,7 @@
 #include <plat/udc.h>
 #include <plat/iic.h>
 
+#include <plat/gpio-cfg.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
@@ -207,16 +208,16 @@ static int h1940_backlight_init(struct device *dev)
 {
 	gpio_request(S3C2410_GPB(0), "Backlight");
 
-	s3c2410_gpio_setpin(S3C2410_GPB(0), 0);
-	s3c2410_gpio_pullup(S3C2410_GPB(0), 0);
-	s3c2410_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPB0_TOUT0);
+	gpio_direction_output(S3C2410_GPB(0), 0);
+	s3c_gpio_setpull(S3C2410_GPB(0), S3C_GPIO_PULL_NONE);
+	s3c_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPB0_TOUT0);
 
 	return 0;
 }
 
 static void h1940_backlight_exit(struct device *dev)
 {
-	s3c2410_gpio_cfgpin(S3C2410_GPB(0), 1/*S3C2410_GPB0_OUTP*/);
+	gpio_direction_output(S3C2410_GPB(0), 1);
 }
 
 static struct platform_pwm_backlight_data backlight_data = {
@@ -245,18 +246,18 @@ static void h1940_lcd_power_set(struct plat_lcd_data *pd,
 
 	if (!power) {
 		/* set to 3ec */
-		s3c2410_gpio_setpin(S3C2410_GPC(0), 0);
+		gpio_direction_output(S3C2410_GPC(0), 0);
 		/* wait for 3ac */
 		do {
-			value = s3c2410_gpio_getpin(S3C2410_GPC(6));
+			value = gpio_get_value(S3C2410_GPC(6));
 		} while (value);
 		/* set to 38c */
-		s3c2410_gpio_setpin(S3C2410_GPC(5), 0);
+		gpio_direction_output(S3C2410_GPC(5), 0);
 	} else {
 		/* Set to 3ac */
-		s3c2410_gpio_setpin(S3C2410_GPC(5), 1);
+		gpio_direction_output(S3C2410_GPC(5), 1);
 		/* Set to 3ad */
-		s3c2410_gpio_setpin(S3C2410_GPC(0), 1);
+		gpio_direction_output(S3C2410_GPC(0), 1);
 	}
 }
 
@@ -333,6 +334,7 @@ static void __init h1940_init(void)
 	gpio_request(S3C2410_GPC(5), "LCD power");
 	gpio_request(S3C2410_GPC(6), "LCD power");
 
+	gpio_direction_input(S3C2410_GPC(6));
 
 	platform_add_devices(h1940_devices, ARRAY_SIZE(h1940_devices));
 }

+ 3 - 0
arch/arm/mach-s3c2410/mach-n30.c

@@ -596,6 +596,9 @@ static void __init n30_init(void)
 
 		platform_add_devices(n35_devices, ARRAY_SIZE(n35_devices));
 	}
+
+	WARN_ON(gpio_request(S3C2410_GPB(3), "udc pup"));
+	gpio_direction_output(S3C2410_GPB(3), 0);
 }
 
 MACHINE_START(N30, "Acer-N30")

+ 6 - 4
arch/arm/mach-s3c2410/mach-qt2410.c

@@ -58,6 +58,7 @@
 #include <plat/iic.h>
 
 #include <plat/common-smdk.h>
+#include <plat/gpio-cfg.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/pm.h>
@@ -219,10 +220,10 @@ static void spi_gpio_cs(struct s3c2410_spigpio_info *spi, int cs)
 {
 	switch (cs) {
 	case BITBANG_CS_ACTIVE:
-		s3c2410_gpio_setpin(S3C2410_GPB(5), 0);
+		gpio_set_value(S3C2410_GPB(5), 0);
 		break;
 	case BITBANG_CS_INACTIVE:
-		s3c2410_gpio_setpin(S3C2410_GPB(5), 1);
+		gpio_set_value(S3C2410_GPB(5), 1);
 		break;
 	}
 }
@@ -347,13 +348,14 @@ static void __init qt2410_machine_init(void)
 	}
 	s3c24xx_fb_set_platdata(&qt2410_fb_info);
 
-	s3c2410_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPIO_OUTPUT);
+	s3c_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPIO_OUTPUT);
 	s3c2410_gpio_setpin(S3C2410_GPB(0), 1);
 
 	s3c24xx_udc_set_platdata(&qt2410_udc_cfg);
 	s3c_i2c0_set_platdata(NULL);
 
-	s3c2410_gpio_cfgpin(S3C2410_GPB(5), S3C2410_GPIO_OUTPUT);
+	WARN_ON(gpio_request(S3C2410_GPB(5), "spi cs"));
+	gpio_direction_output(S3C2410_GPB(5), 1);
 
 	platform_add_devices(qt2410_devices, ARRAY_SIZE(qt2410_devices));
 	s3c_pm_init();

+ 3 - 2
arch/arm/mach-s3c2410/mach-vr1000.c

@@ -357,8 +357,7 @@ static struct clk *vr1000_clocks[] __initdata = {
 
 static void vr1000_power_off(void)
 {
-	s3c2410_gpio_cfgpin(S3C2410_GPB(9), S3C2410_GPIO_OUTPUT);
-	s3c2410_gpio_setpin(S3C2410_GPB(9), 1);
+	gpio_direction_output(S3C2410_GPB(9), 1);
 }
 
 static void __init vr1000_map_io(void)
@@ -395,6 +394,8 @@ static void __init vr1000_init(void)
 
 	nor_simtec_init();
 	simtec_audio_add(NULL, true, NULL);
+
+	WARN_ON(gpio_request(S3C2410_GPB(9), "power off"));
 }
 
 MACHINE_START(VR1000, "Thorcom-VR1000")

+ 8 - 0
arch/arm/mach-s3c2410/s3c2410.c

@@ -16,6 +16,7 @@
 #include <linux/list.h>
 #include <linux/timer.h>
 #include <linux/init.h>
+#include <linux/gpio.h>
 #include <linux/clk.h>
 #include <linux/sysdev.h>
 #include <linux/serial_core.h>
@@ -40,6 +41,10 @@
 #include <plat/clock.h>
 #include <plat/pll.h>
 
+#include <plat/gpio-core.h>
+#include <plat/gpio-cfg.h>
+#include <plat/gpio-cfg-helpers.h>
+
 /* Initial IO mappings */
 
 static struct map_desc s3c2410_iodesc[] __initdata = {
@@ -65,6 +70,9 @@ void __init s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no)
 
 void __init s3c2410_map_io(void)
 {
+	s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_1up;
+	s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_1up;
+
 	iotable_init(s3c2410_iodesc, ARRAY_SIZE(s3c2410_iodesc));
 }
 

+ 11 - 9
arch/arm/mach-s3c2412/gpio.c

@@ -16,41 +16,43 @@
 #include <linux/types.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
+#include <linux/gpio.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
 #include <mach/regs-gpio.h>
-
 #include <mach/hardware.h>
 
+#include <plat/gpio-core.h>
+
 int s3c2412_gpio_set_sleepcfg(unsigned int pin, unsigned int state)
 {
-	void __iomem *base = S3C24XX_GPIO_BASE(pin);
-	unsigned long offs = S3C2410_GPIO_OFFSET(pin);
+	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
+	unsigned long offs = pin - chip->chip.base;
 	unsigned long flags;
 	unsigned long slpcon;
 
 	offs *= 2;
 
-	if (pin < S3C2410_GPIO_BANKB)
+	if (pin < S3C2410_GPB(0))
 		return -EINVAL;
 
-	if (pin >= S3C2410_GPIO_BANKF &&
-	    pin <= S3C2410_GPIO_BANKG)
+	if (pin >= S3C2410_GPF(0) &&
+	    pin <= S3C2410_GPG(16))
 		return -EINVAL;
 
-	if (pin > (S3C2410_GPIO_BANKH + 32))
+	if (pin > S3C2410_GPH(16))
 		return -EINVAL;
 
 	local_irq_save(flags);
 
-	slpcon = __raw_readl(base + 0x0C);
+	slpcon = __raw_readl(chip->base + 0x0C);
 
 	slpcon &= ~(3 << offs);
 	slpcon |= state << offs;
 
-	__raw_writel(slpcon, base + 0x0C);
+	__raw_writel(slpcon, chip->base + 0x0C);
 
 	local_irq_restore(flags);
 

+ 13 - 13
arch/arm/mach-s3c2412/mach-jive.c

@@ -48,6 +48,7 @@
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 
+#include <plat/gpio-cfg.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
@@ -357,8 +358,7 @@ static void jive_lcm_reset(unsigned int set)
 {
 	printk(KERN_DEBUG "%s(%d)\n", __func__, set);
 
-	s3c2410_gpio_setpin(S3C2410_GPG(13), set);
-	s3c2410_gpio_cfgpin(S3C2410_GPG(13), S3C2410_GPIO_OUTPUT);
+	gpio_set_value(S3C2410_GPG(13), set);
 }
 
 #undef LCD_UPPER_MARGIN
@@ -391,7 +391,7 @@ static struct ili9320_platdata jive_lcm_config = {
 
 static void jive_lcd_spi_chipselect(struct s3c2410_spigpio_info *spi, int cs)
 {
-	s3c2410_gpio_setpin(S3C2410_GPB(7), cs ? 0 : 1);
+	gpio_set_value(S3C2410_GPB(7), cs ? 0 : 1);
 }
 
 static struct s3c2410_spigpio_info jive_lcd_spi = {
@@ -413,7 +413,7 @@ static struct platform_device jive_device_lcdspi = {
 
 static void jive_wm8750_chipselect(struct s3c2410_spigpio_info *spi, int cs)
 {
-	s3c2410_gpio_setpin(S3C2410_GPH(10), cs ? 0 : 1);
+	gpio_set_value(S3C2410_GPH(10), cs ? 0 : 1);
 }
 
 static struct s3c2410_spigpio_info jive_wm8750_spi = {
@@ -531,7 +531,7 @@ static void jive_power_off(void)
 	printk(KERN_INFO "powering system down...\n");
 
 	s3c2410_gpio_setpin(S3C2410_GPC(5), 1);
-	s3c2410_gpio_cfgpin(S3C2410_GPC(5), S3C2410_GPIO_OUTPUT);
+	s3c_gpio_cfgpin(S3C2410_GPC(5), S3C2410_GPIO_OUTPUT);
 }
 
 static void __init jive_machine_init(void)
@@ -636,22 +636,22 @@ static void __init jive_machine_init(void)
 
 	/* initialise the spi */
 
-	s3c2410_gpio_setpin(S3C2410_GPG(13), 0);
-	s3c2410_gpio_cfgpin(S3C2410_GPG(13), S3C2410_GPIO_OUTPUT);
+	gpio_request(S3C2410_GPG(13), "lcm reset");
+	gpio_direction_output(S3C2410_GPG(13), 0);
 
-	s3c2410_gpio_setpin(S3C2410_GPB(7), 1);
-	s3c2410_gpio_cfgpin(S3C2410_GPB(7), S3C2410_GPIO_OUTPUT);
+	gpio_request(S3C2410_GPB(7), "jive spi");
+	gpio_direction_output(S3C2410_GPB(7), 1);
 
 	s3c2410_gpio_setpin(S3C2410_GPB(6), 0);
-	s3c2410_gpio_cfgpin(S3C2410_GPB(6), S3C2410_GPIO_OUTPUT);
+	s3c_gpio_cfgpin(S3C2410_GPB(6), S3C2410_GPIO_OUTPUT);
 
 	s3c2410_gpio_setpin(S3C2410_GPG(8), 1);
-	s3c2410_gpio_cfgpin(S3C2410_GPG(8), S3C2410_GPIO_OUTPUT);
+	s3c_gpio_cfgpin(S3C2410_GPG(8), S3C2410_GPIO_OUTPUT);
 
 	/* initialise the WM8750 spi */
 
-	s3c2410_gpio_setpin(S3C2410_GPH(10), 1);
-	s3c2410_gpio_cfgpin(S3C2410_GPH(10), S3C2410_GPIO_OUTPUT);
+	gpio_request(S3C2410_GPH(10), "jive wm8750 spi");
+	gpio_direction_output(S3C2410_GPH(10), 1);
 
 	/* Turn off suspend on both USB ports, and switch the
 	 * selectable USB port to USB device mode. */

+ 4 - 4
arch/arm/mach-s3c2412/mach-smdk2413.c

@@ -85,10 +85,10 @@ static void smdk2413_udc_pullup(enum s3c2410_udc_cmd_e cmd)
 	switch (cmd)
 	{
 		case S3C2410_UDC_P_ENABLE :
-			s3c2410_gpio_setpin(S3C2410_GPF(2), 1);
+			gpio_set_value(S3C2410_GPF(2), 1);
 			break;
 		case S3C2410_UDC_P_DISABLE :
-			s3c2410_gpio_setpin(S3C2410_GPF(2), 0);
+			gpio_set_value(S3C2410_GPF(2), 0);
 			break;
 		case S3C2410_UDC_P_RESET :
 			break;
@@ -134,8 +134,8 @@ static void __init smdk2413_machine_init(void)
 {	/* Turn off suspend on both USB ports, and switch the
 	 * selectable USB port to USB device mode. */
 
-	s3c2410_gpio_setpin(S3C2410_GPF(2), 0);
-	s3c2410_gpio_cfgpin(S3C2410_GPF(2), S3C2410_GPIO_OUTPUT);
+	WARN_ON(gpio_request(S3C2410_GPF(2), "udc pull"));
+	gpio_direction_output(S3C2410_GPF(2), 0);
 
 	s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST |
 			      S3C2410_MISCCR_USBSUSPND0 |

+ 1 - 0
arch/arm/mach-s3c2440/Kconfig

@@ -6,6 +6,7 @@ config CPU_S3C2440
 	bool
 	depends on ARCH_S3C2410
 	select CPU_ARM920T
+	select S3C_GPIO_PULL_UP
 	select S3C2410_CLOCK
 	select S3C2410_PM if PM
 	select S3C2410_GPIO

+ 12 - 11
arch/arm/mach-s3c2440/mach-mini2440.c

@@ -53,6 +53,7 @@
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 
+#include <plat/gpio-cfg.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
@@ -102,10 +103,10 @@ static void mini2440_udc_pullup(enum s3c2410_udc_cmd_e cmd)
 
 	switch (cmd) {
 		case S3C2410_UDC_P_ENABLE :
-			s3c2410_gpio_setpin(S3C2410_GPC(5), 1);
+			gpio_set_value(S3C2410_GPC(5), 1);
 			break;
 		case S3C2410_UDC_P_DISABLE :
-			s3c2410_gpio_setpin(S3C2410_GPC(5), 0);
+			gpio_set_value(S3C2410_GPC(5), 0);
 			break;
 		case S3C2410_UDC_P_RESET :
 			break;
@@ -632,25 +633,25 @@ static void __init mini2440_init(void)
 	mini2440_parse_features(&features, mini2440_features_str);
 
 	/* turn LCD on */
-	s3c2410_gpio_cfgpin(S3C2410_GPC(0), S3C2410_GPC0_LEND);
+	s3c_gpio_cfgpin(S3C2410_GPC(0), S3C2410_GPC0_LEND);
 
 	/* Turn the backlight early on */
-	s3c2410_gpio_setpin(S3C2410_GPG(4), 1);
-	s3c2410_gpio_cfgpin(S3C2410_GPG(4), S3C2410_GPIO_OUTPUT);
+	WARN_ON(gpio_request(S3C2410_GPG(4), "backlight"));
+	gpio_direction_output(S3C2410_GPG(4), 1);
 
 	/* remove pullup on optional PWM backlight -- unused on 3.5 and 7"s */
-	s3c2410_gpio_pullup(S3C2410_GPB(1), 0);
+	s3c_gpio_setpull(S3C2410_GPB(1), S3C_GPIO_PULL_UP);
 	s3c2410_gpio_setpin(S3C2410_GPB(1), 0);
-	s3c2410_gpio_cfgpin(S3C2410_GPB(1), S3C2410_GPIO_INPUT);
+	s3c_gpio_cfgpin(S3C2410_GPB(1), S3C2410_GPIO_INPUT);
 
 	/* Make sure the D+ pullup pin is output */
-	s3c2410_gpio_cfgpin(S3C2410_GPC(5), S3C2410_GPIO_OUTPUT);
+	WARN_ON(gpio_request(S3C2410_GPC(5), "udc pup"));
+	gpio_direction_output(S3C2410_GPC(5), 0);
 
 	/* mark the key as input, without pullups (there is one on the board) */
 	for (i = 0; i < ARRAY_SIZE(mini2440_buttons); i++) {
-		s3c2410_gpio_pullup(mini2440_buttons[i].gpio, 0);
-		s3c2410_gpio_cfgpin(mini2440_buttons[i].gpio,
-					S3C2410_GPIO_INPUT);
+		s3c_gpio_setpull(mini2440_buttons[i].gpio, S3C_GPIO_PULL_UP);
+		s3c_gpio_cfgpin(mini2440_buttons[i].gpio, S3C2410_GPIO_INPUT);
 	}
 	if (features.lcd_index != -1) {
 		int li;

+ 5 - 4
arch/arm/mach-s3c2440/mach-nexcoder.c

@@ -40,6 +40,7 @@
 #include <plat/regs-serial.h>
 #include <plat/iic.h>
 
+#include <plat/gpio-cfg.h>
 #include <plat/s3c2410.h>
 #include <plat/s3c244x.h>
 #include <plat/clock.h>
@@ -122,15 +123,15 @@ static void __init nexcoder_sensorboard_init(void)
 {
 	// Initialize SCCB bus
 	s3c2410_gpio_setpin(S3C2410_GPE(14), 1); // IICSCL
-	s3c2410_gpio_cfgpin(S3C2410_GPE(14), S3C2410_GPIO_OUTPUT);
+	s3c_gpio_cfgpin(S3C2410_GPE(14), S3C2410_GPIO_OUTPUT);
 	s3c2410_gpio_setpin(S3C2410_GPE(15), 1); // IICSDA
-	s3c2410_gpio_cfgpin(S3C2410_GPE(15), S3C2410_GPIO_OUTPUT);
+	s3c_gpio_cfgpin(S3C2410_GPE(15), S3C2410_GPIO_OUTPUT);
 
 	// Power up the sensor board
 	s3c2410_gpio_setpin(S3C2410_GPF(1), 1);
-	s3c2410_gpio_cfgpin(S3C2410_GPF(1), S3C2410_GPIO_OUTPUT); // CAM_GPIO7 => nLDO_PWRDN
+	s3c_gpio_cfgpin(S3C2410_GPF(1), S3C2410_GPIO_OUTPUT); // CAM_GPIO7 => nLDO_PWRDN
 	s3c2410_gpio_setpin(S3C2410_GPF(2), 0);
-	s3c2410_gpio_cfgpin(S3C2410_GPF(2), S3C2410_GPIO_OUTPUT); // CAM_GPIO6 => CAM_PWRDN
+	s3c_gpio_cfgpin(S3C2410_GPF(2), S3C2410_GPIO_OUTPUT); // CAM_GPIO6 => CAM_PWRDN
 }
 
 static void __init nexcoder_map_io(void)

+ 3 - 2
arch/arm/mach-s3c2440/mach-osiris.c

@@ -49,6 +49,7 @@
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 
+#include <plat/gpio-cfg.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
@@ -298,7 +299,7 @@ static int osiris_pm_suspend(struct sys_device *sd, pm_message_t state)
 
 	/* ensure that an nRESET is not generated on resume. */
 	s3c2410_gpio_setpin(S3C2410_GPA(21), 1);
-	s3c2410_gpio_cfgpin(S3C2410_GPA(21), S3C2410_GPIO_OUTPUT);
+	s3c_gpio_cfgpin(S3C2410_GPA(21), S3C2410_GPIO_OUTPUT);
 
 	return 0;
 }
@@ -310,7 +311,7 @@ static int osiris_pm_resume(struct sys_device *sd)
 
 	__raw_writeb(pm_osiris_ctrl0, OSIRIS_VA_CTRL0);
 
-	s3c2410_gpio_cfgpin(S3C2410_GPA(21), S3C2410_GPA21_nRSTOUT);
+	s3c_gpio_cfgpin(S3C2410_GPA(21), S3C2410_GPA21_nRSTOUT);
 
 	return 0;
 }

+ 8 - 0
arch/arm/mach-s3c2440/s3c2440.c

@@ -19,6 +19,7 @@
 #include <linux/platform_device.h>
 #include <linux/serial_core.h>
 #include <linux/sysdev.h>
+#include <linux/gpio.h>
 #include <linux/clk.h>
 #include <linux/io.h>
 
@@ -33,6 +34,10 @@
 #include <plat/cpu.h>
 #include <plat/s3c244x.h>
 
+#include <plat/gpio-core.h>
+#include <plat/gpio-cfg.h>
+#include <plat/gpio-cfg-helpers.h>
+
 static struct sys_device s3c2440_sysdev = {
 	.cls		= &s3c2440_sysclass,
 };
@@ -41,6 +46,9 @@ int __init s3c2440_init(void)
 {
 	printk("S3C2440: Initialising architecture\n");
 
+	s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_1up;
+	s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_1up;
+
 	/* change irq for watchdog */
 
 	s3c_device_wdt.resource[1].start = IRQ_S3C2440_WDT;

+ 6 - 0
arch/arm/mach-s3c64xx/gpiolib.c

@@ -51,6 +51,7 @@
 
 static struct s3c_gpio_cfg gpio_4bit_cfg_noint = {
 	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
+	.get_config	= s3c_gpio_getcfg_s3c64xx_4bit,
 	.set_pull	= s3c_gpio_setpull_updown,
 	.get_pull	= s3c_gpio_getpull_updown,
 };
@@ -58,12 +59,14 @@ static struct s3c_gpio_cfg gpio_4bit_cfg_noint = {
 static struct s3c_gpio_cfg gpio_4bit_cfg_eint0111 = {
 	.cfg_eint	= 7,
 	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
+	.get_config	= s3c_gpio_getcfg_s3c64xx_4bit,
 	.set_pull	= s3c_gpio_setpull_updown,
 	.get_pull	= s3c_gpio_getpull_updown,
 };
 
 static struct s3c_gpio_cfg gpio_4bit_cfg_eint0011 = {
 	.cfg_eint	= 3,
+	.get_config	= s3c_gpio_getcfg_s3c64xx_4bit,
 	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
 	.set_pull	= s3c_gpio_setpull_updown,
 	.get_pull	= s3c_gpio_getpull_updown,
@@ -171,6 +174,7 @@ static struct s3c_gpio_chip gpio_4bit2[] = {
 
 static struct s3c_gpio_cfg gpio_2bit_cfg_noint = {
 	.set_config	= s3c_gpio_setcfg_s3c24xx,
+	.get_config	= s3c_gpio_getcfg_s3c24xx,
 	.set_pull	= s3c_gpio_setpull_updown,
 	.get_pull	= s3c_gpio_getpull_updown,
 };
@@ -178,6 +182,7 @@ static struct s3c_gpio_cfg gpio_2bit_cfg_noint = {
 static struct s3c_gpio_cfg gpio_2bit_cfg_eint10 = {
 	.cfg_eint	= 2,
 	.set_config	= s3c_gpio_setcfg_s3c24xx,
+	.get_config	= s3c_gpio_getcfg_s3c24xx,
 	.set_pull	= s3c_gpio_setpull_updown,
 	.get_pull	= s3c_gpio_getpull_updown,
 };
@@ -185,6 +190,7 @@ static struct s3c_gpio_cfg gpio_2bit_cfg_eint10 = {
 static struct s3c_gpio_cfg gpio_2bit_cfg_eint11 = {
 	.cfg_eint	= 3,
 	.set_config	= s3c_gpio_setcfg_s3c24xx,
+	.get_config	= s3c_gpio_getcfg_s3c24xx,
 	.set_pull	= s3c_gpio_setpull_updown,
 	.get_pull	= s3c_gpio_getpull_updown,
 };

+ 5 - 0
arch/arm/mach-s5p6440/gpio.c

@@ -161,12 +161,15 @@ static struct s3c_gpio_cfg s5p6440_gpio_cfgs[] = {
 	}, {
 		.cfg_eint	= 0,
 		.set_config	= s3c_gpio_setcfg_s3c24xx,
+		.get_config	= s3c_gpio_getcfg_s3c24xx,
 	}, {
 		.cfg_eint	= 2,
 		.set_config	= s3c_gpio_setcfg_s3c24xx,
+		.get_config	= s3c_gpio_getcfg_s3c24xx,
 	}, {
 		.cfg_eint	= 3,
 		.set_config	= s3c_gpio_setcfg_s3c24xx,
+		.get_config	= s3c_gpio_getcfg_s3c24xx,
 	},
 };
 
@@ -279,6 +282,8 @@ void __init s5p6440_gpiolib_set_cfg(struct s3c_gpio_cfg *chipcfg, int nr_chips)
 	for (; nr_chips > 0; nr_chips--, chipcfg++) {
 		if (!chipcfg->set_config)
 			chipcfg->set_config	= s3c_gpio_setcfg_s3c64xx_4bit;
+		if (!chipcfg->get_config)
+			chipcfg->get_config	= s3c_gpio_getcfg_s3c64xx_4bit;
 		if (!chipcfg->set_pull)
 			chipcfg->set_pull	= s3c_gpio_setpull_updown;
 		if (!chipcfg->get_pull)

+ 1 - 0
arch/arm/plat-s3c24xx/Kconfig

@@ -9,6 +9,7 @@ config PLAT_S3C24XX
 	select NO_IOPORT
 	select ARCH_REQUIRE_GPIOLIB
 	select S3C_DEVICE_NAND
+	select S3C_GPIO_CFG_S3C24XX
 	help
 	  Base platform code for any Samsung S3C24XX device
 

+ 5 - 4
arch/arm/plat-s3c24xx/common-smdk.c

@@ -42,6 +42,7 @@
 #include <plat/nand.h>
 
 #include <plat/common-smdk.h>
+#include <plat/gpio-cfg.h>
 #include <plat/devs.h>
 #include <plat/pm.h>
 
@@ -185,10 +186,10 @@ void __init smdk_machine_init(void)
 {
 	/* Configure the LEDs (even if we have no LED support)*/
 
-	s3c2410_gpio_cfgpin(S3C2410_GPF(4), S3C2410_GPIO_OUTPUT);
-	s3c2410_gpio_cfgpin(S3C2410_GPF(5), S3C2410_GPIO_OUTPUT);
-	s3c2410_gpio_cfgpin(S3C2410_GPF(6), S3C2410_GPIO_OUTPUT);
-	s3c2410_gpio_cfgpin(S3C2410_GPF(7), S3C2410_GPIO_OUTPUT);
+	s3c_gpio_cfgpin(S3C2410_GPF(4), S3C2410_GPIO_OUTPUT);
+	s3c_gpio_cfgpin(S3C2410_GPF(5), S3C2410_GPIO_OUTPUT);
+	s3c_gpio_cfgpin(S3C2410_GPF(6), S3C2410_GPIO_OUTPUT);
+	s3c_gpio_cfgpin(S3C2410_GPF(7), S3C2410_GPIO_OUTPUT);
 
 	s3c2410_gpio_setpin(S3C2410_GPF(4), 1);
 	s3c2410_gpio_setpin(S3C2410_GPF(5), 1);

+ 22 - 128
arch/arm/plat-s3c24xx/gpio.c

@@ -1,6 +1,6 @@
 /* linux/arch/arm/plat-s3c24xx/gpio.c
  *
- * Copyright (c) 2004-2005 Simtec Electronics
+ * Copyright (c) 2004-2010 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
  *
  * S3C24XX GPIO support
@@ -20,12 +20,12 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 
-
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
+#include <linux/gpio.h>
 #include <linux/io.h>
 
 #include <mach/hardware.h>
@@ -34,133 +34,46 @@
 
 #include <mach/regs-gpio.h>
 
-void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
-{
-	void __iomem *base = S3C24XX_GPIO_BASE(pin);
-	unsigned long mask;
-	unsigned long con;
-	unsigned long flags;
+#include <plat/gpio-core.h>
 
-	if (pin < S3C2410_GPIO_BANKB) {
-		mask = 1 << S3C2410_GPIO_OFFSET(pin);
-	} else {
-		mask = 3 << S3C2410_GPIO_OFFSET(pin)*2;
-	}
-
-	switch (function) {
-	case S3C2410_GPIO_LEAVE:
-		mask = 0;
-		function = 0;
-		break;
-
-	case S3C2410_GPIO_INPUT:
-	case S3C2410_GPIO_OUTPUT:
-	case S3C2410_GPIO_SFN2:
-	case S3C2410_GPIO_SFN3:
-		if (pin < S3C2410_GPIO_BANKB) {
-			function -= 1;
-			function &= 1;
-			function <<= S3C2410_GPIO_OFFSET(pin);
-		} else {
-			function &= 3;
-			function <<= S3C2410_GPIO_OFFSET(pin)*2;
-		}
-	}
-
-	/* modify the specified register wwith IRQs off */
-
-	local_irq_save(flags);
-
-	con  = __raw_readl(base + 0x00);
-	con &= ~mask;
-	con |= function;
-
-	__raw_writel(con, base + 0x00);
-
-	local_irq_restore(flags);
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_cfgpin);
-
-unsigned int s3c2410_gpio_getcfg(unsigned int pin)
-{
-	void __iomem *base = S3C24XX_GPIO_BASE(pin);
-	unsigned long val = __raw_readl(base);
-
-	if (pin < S3C2410_GPIO_BANKB) {
-		val >>= S3C2410_GPIO_OFFSET(pin);
-		val &= 1;
-		val += 1;
-	} else {
-		val >>= S3C2410_GPIO_OFFSET(pin)*2;
-		val &= 3;
-	}
-
-	return val | S3C2410_GPIO_INPUT;
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_getcfg);
+/* gpiolib wrappers until these are totally eliminated */
 
 void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
 {
-	void __iomem *base = S3C24XX_GPIO_BASE(pin);
-	unsigned long offs = S3C2410_GPIO_OFFSET(pin);
-	unsigned long flags;
-	unsigned long up;
+	int ret;
 
-	if (pin < S3C2410_GPIO_BANKB)
-		return;
+	WARN_ON(to);	/* should be none of these left */
 
-	local_irq_save(flags);
-
-	up = __raw_readl(base + 0x08);
-	up &= ~(1L << offs);
-	up |= to << offs;
-	__raw_writel(up, base + 0x08);
+	if (!to) {
+		/* if pull is enabled, try first with up, and if that
+		 * fails, try using down */
 
-	local_irq_restore(flags);
+		ret = s3c_gpio_setpull(pin, S3C_GPIO_PULL_UP);
+		if (ret)
+			s3c_gpio_setpull(pin, S3C_GPIO_PULL_DOWN);
+	} else {
+		s3c_gpio_setpull(pin, S3C_GPIO_PULL_NONE);
+	}
 }
-
 EXPORT_SYMBOL(s3c2410_gpio_pullup);
 
-int s3c2410_gpio_getpull(unsigned int pin)
-{
-	void __iomem *base = S3C24XX_GPIO_BASE(pin);
-	unsigned long offs = S3C2410_GPIO_OFFSET(pin);
-
-	if (pin < S3C2410_GPIO_BANKB)
-		return -EINVAL;
-
-	return (__raw_readl(base + 0x08) & (1L << offs)) ? 1 : 0;
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_getpull);
-
 void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
 {
-	void __iomem *base = S3C24XX_GPIO_BASE(pin);
-	unsigned long offs = S3C2410_GPIO_OFFSET(pin);
-	unsigned long flags;
-	unsigned long dat;
+	/* do this via gpiolib until all users removed */
 
-	local_irq_save(flags);
-
-	dat = __raw_readl(base + 0x04);
-	dat &= ~(1 << offs);
-	dat |= to << offs;
-	__raw_writel(dat, base + 0x04);
-
-	local_irq_restore(flags);
+	gpio_request(pin, "temporary");
+	gpio_set_value(pin, to);
+	gpio_free(pin);
 }
 
 EXPORT_SYMBOL(s3c2410_gpio_setpin);
 
 unsigned int s3c2410_gpio_getpin(unsigned int pin)
 {
-	void __iomem *base = S3C24XX_GPIO_BASE(pin);
-	unsigned long offs = S3C2410_GPIO_OFFSET(pin);
+	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
+	unsigned long offs = pin - chip->chip.base;
 
-	return __raw_readl(base + 0x04) & (1<< offs);
+	return __raw_readl(chip->base + 0x04) & (1<< offs);
 }
 
 EXPORT_SYMBOL(s3c2410_gpio_getpin);
@@ -181,22 +94,3 @@ unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
 }
 
 EXPORT_SYMBOL(s3c2410_modify_misccr);
-
-int s3c2410_gpio_getirq(unsigned int pin)
-{
-	if (pin < S3C2410_GPF(0) || pin > S3C2410_GPG(15))
-		return -EINVAL;	/* not valid interrupts */
-
-	if (pin < S3C2410_GPG(0) && pin > S3C2410_GPF(7))
-		return -EINVAL;	/* not valid pin */
-
-	if (pin < S3C2410_GPF(4))
-		return (pin - S3C2410_GPF(0)) + IRQ_EINT0;
-
-	if (pin < S3C2410_GPG(0))
-		return (pin - S3C2410_GPF(4)) + IRQ_EINT4;
-
-	return (pin - S3C2410_GPG(0)) + IRQ_EINT8;
-}
-
-EXPORT_SYMBOL(s3c2410_gpio_getirq);

+ 58 - 2
arch/arm/plat-s3c24xx/gpiolib.c

@@ -1,6 +1,6 @@
 /* linux/arch/arm/plat-s3c24xx/gpiolib.c
  *
- * Copyright (c) 2008 Simtec Electronics
+ * Copyright (c) 2008-2010 Simtec Electronics
  *	http://armlinux.simtec.co.uk/
  *	Ben Dooks <ben@simtec.co.uk>
  *
@@ -21,6 +21,8 @@
 #include <linux/gpio.h>
 
 #include <plat/gpio-core.h>
+#include <plat/gpio-cfg.h>
+#include <plat/gpio-cfg-helpers.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
 #include <plat/pm.h>
@@ -77,10 +79,21 @@ static int s3c24xx_gpiolib_bankg_toirq(struct gpio_chip *chip, unsigned offset)
 	return IRQ_EINT8 + offset;
 }
 
+static struct s3c_gpio_cfg s3c24xx_gpiocfg_banka = {
+	.set_config	= s3c_gpio_setcfg_s3c24xx_a,
+	.get_config	= s3c_gpio_getcfg_s3c24xx_a,
+};
+
+struct s3c_gpio_cfg s3c24xx_gpiocfg_default = {
+	.set_config	= s3c_gpio_setcfg_s3c24xx,
+	.get_config	= s3c_gpio_getcfg_s3c24xx,
+};
+
 struct s3c_gpio_chip s3c24xx_gpios[] = {
 	[0] = {
 		.base	= S3C2410_GPACON,
 		.pm	= __gpio_pm(&s3c_gpio_pm_1bit),
+		.config	= &s3c24xx_gpiocfg_banka,
 		.chip	= {
 			.base			= S3C2410_GPA(0),
 			.owner			= THIS_MODULE,
@@ -161,15 +174,58 @@ struct s3c_gpio_chip s3c24xx_gpios[] = {
 			.ngpio			= 11,
 		},
 	},
+		/* GPIOS for the S3C2443 and later devices. */
+	{
+		.base	= S3C2440_GPJCON,
+		.pm	= __gpio_pm(&s3c_gpio_pm_2bit),
+		.chip	= {
+			.base			= S3C2410_GPJ(0),
+			.owner			= THIS_MODULE,
+			.label			= "GPIOJ",
+			.ngpio			= 16,
+		},
+	}, {
+		.base	= S3C2443_GPKCON,
+		.pm	= __gpio_pm(&s3c_gpio_pm_2bit),
+		.chip	= {
+			.base			= S3C2410_GPK(0),
+			.owner			= THIS_MODULE,
+			.label			= "GPIOK",
+			.ngpio			= 16,
+		},
+	}, {
+		.base	= S3C2443_GPLCON,
+		.pm	= __gpio_pm(&s3c_gpio_pm_2bit),
+		.chip	= {
+			.base			= S3C2410_GPL(0),
+			.owner			= THIS_MODULE,
+			.label			= "GPIOL",
+			.ngpio			= 15,
+		},
+	}, {
+		.base	= S3C2443_GPMCON,
+		.pm	= __gpio_pm(&s3c_gpio_pm_2bit),
+		.chip	= {
+			.base			= S3C2410_GPM(0),
+			.owner			= THIS_MODULE,
+			.label			= "GPIOM",
+			.ngpio			= 2,
+		},
+	},
 };
 
+
 static __init int s3c24xx_gpiolib_init(void)
 {
 	struct s3c_gpio_chip *chip = s3c24xx_gpios;
 	int gpn;
 
-	for (gpn = 0; gpn < ARRAY_SIZE(s3c24xx_gpios); gpn++, chip++)
+	for (gpn = 0; gpn < ARRAY_SIZE(s3c24xx_gpios); gpn++, chip++) {
+		if (!chip->config)
+			chip->config = &s3c24xx_gpiocfg_default;
+
 		s3c_gpiolib_add(chip);
+	}
 
 	return 0;
 }

+ 5 - 4
arch/arm/plat-s3c24xx/pm.c

@@ -43,6 +43,7 @@
 
 #include <asm/mach/time.h>
 
+#include <plat/gpio-cfg.h>
 #include <plat/pm.h>
 
 #define PFX "s3c24xx-pm: "
@@ -90,22 +91,22 @@ static void s3c_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs)
 {
 	unsigned long irqstate;
 	unsigned long pinstate;
-	int irq = s3c2410_gpio_getirq(pin);
+	int irq = gpio_to_irq(pin);
 
 	if (irqoffs < 4)
 		irqstate = s3c_irqwake_intmask & (1L<<irqoffs);
 	else
 		irqstate = s3c_irqwake_eintmask & (1L<<irqoffs);
 
-	pinstate = s3c2410_gpio_getcfg(pin);
+	pinstate = s3c_gpio_getcfg(pin);
 
 	if (!irqstate) {
 		if (pinstate == S3C2410_GPIO_IRQ)
-			S3C_PMDBG("Leaving IRQ %d (pin %d) enabled\n", irq, pin);
+			S3C_PMDBG("Leaving IRQ %d (pin %d) as is\n", irq, pin);
 	} else {
 		if (pinstate == S3C2410_GPIO_IRQ) {
 			S3C_PMDBG("Disabling IRQ %d (pin %d)\n", irq, pin);
-			s3c2410_gpio_cfgpin(pin, S3C2410_GPIO_INPUT);
+			s3c_gpio_cfgpin(pin, S3C2410_GPIO_INPUT);
 		}
 	}
 }

+ 3 - 2
arch/arm/plat-s3c24xx/setup-i2c.c

@@ -15,12 +15,13 @@
 
 struct platform_device;
 
+#include <plat/gpio-cfg.h>
 #include <plat/iic.h>
 #include <mach/hardware.h>
 #include <mach/regs-gpio.h>
 
 void s3c_i2c0_cfg_gpio(struct platform_device *dev)
 {
-	s3c2410_gpio_cfgpin(S3C2410_GPE(15), S3C2410_GPE15_IICSDA);
-	s3c2410_gpio_cfgpin(S3C2410_GPE(14), S3C2410_GPE14_IICSCL);
+	s3c_gpio_cfgpin(S3C2410_GPE(15), S3C2410_GPE15_IICSDA);
+	s3c_gpio_cfgpin(S3C2410_GPE(14), S3C2410_GPE14_IICSCL);
 }

+ 8 - 8
arch/arm/plat-s3c24xx/spi-bus0-gpe11_12_13.c

@@ -21,16 +21,16 @@ void s3c24xx_spi_gpiocfg_bus0_gpe11_12_13(struct s3c2410_spi_info *spi,
 					  int enable)
 {
 	if (enable) {
-		s3c2410_gpio_cfgpin(S3C2410_GPE(13), S3C2410_GPE13_SPICLK0);
-		s3c2410_gpio_cfgpin(S3C2410_GPE(12), S3C2410_GPE12_SPIMOSI0);
-		s3c2410_gpio_cfgpin(S3C2410_GPE(11), S3C2410_GPE11_SPIMISO0);
+		s3c_gpio_cfgpin(S3C2410_GPE(13), S3C2410_GPE13_SPICLK0);
+		s3c_gpio_cfgpin(S3C2410_GPE(12), S3C2410_GPE12_SPIMOSI0);
+		s3c_gpio_cfgpin(S3C2410_GPE(11), S3C2410_GPE11_SPIMISO0);
 		s3c2410_gpio_pullup(S3C2410_GPE(11), 0);
 		s3c2410_gpio_pullup(S3C2410_GPE(13), 0);
 	} else {
-		s3c2410_gpio_cfgpin(S3C2410_GPE(13), S3C2410_GPIO_INPUT);
-		s3c2410_gpio_cfgpin(S3C2410_GPE(11), S3C2410_GPIO_INPUT);
-		s3c2410_gpio_pullup(S3C2410_GPE(11), 1);
-		s3c2410_gpio_pullup(S3C2410_GPE(12), 1);
-		s3c2410_gpio_pullup(S3C2410_GPE(13), 1);
+		s3c_gpio_cfgpin(S3C2410_GPE(13), S3C2410_GPIO_INPUT);
+		s3c_gpio_cfgpin(S3C2410_GPE(11), S3C2410_GPIO_INPUT);
+		s3c_gpio_cfgpull(S3C2410_GPE(11), S3C_GPIO_PULL_NONE);
+		s3c_gpio_cfgpull(S3C2410_GPE(12), S3C_GPIO_PULL_NONE);
+		s3c_gpio_cfgpull(S3C2410_GPE(13), S3C_GPIO_PULL_NONE);
 	}
 }

+ 8 - 8
arch/arm/plat-s3c24xx/spi-bus1-gpd8_9_10.c

@@ -23,16 +23,16 @@ void s3c24xx_spi_gpiocfg_bus1_gpd8_9_10(struct s3c2410_spi_info *spi,
 
 	printk(KERN_INFO "%s(%d)\n", __func__, enable);
 	if (enable) {
-		s3c2410_gpio_cfgpin(S3C2410_GPD(10), S3C2440_GPD10_SPICLK1);
-		s3c2410_gpio_cfgpin(S3C2410_GPD(9), S3C2440_GPD9_SPIMOSI1);
-		s3c2410_gpio_cfgpin(S3C2410_GPD(8), S3C2440_GPD8_SPIMISO1);
+		s3c_gpio_cfgpin(S3C2410_GPD(10), S3C2440_GPD10_SPICLK1);
+		s3c_gpio_cfgpin(S3C2410_GPD(9), S3C2440_GPD9_SPIMOSI1);
+		s3c_gpio_cfgpin(S3C2410_GPD(8), S3C2440_GPD8_SPIMISO1);
 		s3c2410_gpio_pullup(S3C2410_GPD(10), 0);
 		s3c2410_gpio_pullup(S3C2410_GPD(9), 0);
 	} else {
-		s3c2410_gpio_cfgpin(S3C2410_GPD(8), S3C2410_GPIO_INPUT);
-		s3c2410_gpio_cfgpin(S3C2410_GPD(9), S3C2410_GPIO_INPUT);
-		s3c2410_gpio_pullup(S3C2410_GPD(10), 1);
-		s3c2410_gpio_pullup(S3C2410_GPD(9), 1);
-		s3c2410_gpio_pullup(S3C2410_GPD(8), 1);
+		s3c_gpio_cfgpin(S3C2410_GPD(8), S3C2410_GPIO_INPUT);
+		s3c_gpio_cfgpin(S3C2410_GPD(9), S3C2410_GPIO_INPUT);
+		s3c_gpio_cfgpull(S3C2410_GPD(10), S3C_GPIO_PULL_NONE);
+		s3c_gpio_cfgpull(S3C2410_GPD(9), S3C_GPIO_PULL_NONE);
+		s3c_gpio_cfgpull(S3C2410_GPD(8), S3C_GPIO_PULL_NONE);
 	}
 }

+ 8 - 8
arch/arm/plat-s3c24xx/spi-bus1-gpg5_6_7.c

@@ -21,16 +21,16 @@ void s3c24xx_spi_gpiocfg_bus1_gpg5_6_7(struct s3c2410_spi_info *spi,
 				       int enable)
 {
 	if (enable) {
-		s3c2410_gpio_cfgpin(S3C2410_GPG(7), S3C2410_GPG7_SPICLK1);
-		s3c2410_gpio_cfgpin(S3C2410_GPG(6), S3C2410_GPG6_SPIMOSI1);
-		s3c2410_gpio_cfgpin(S3C2410_GPG(5), S3C2410_GPG5_SPIMISO1);
+		s3c_gpio_cfgpin(S3C2410_GPG(7), S3C2410_GPG7_SPICLK1);
+		s3c_gpio_cfgpin(S3C2410_GPG(6), S3C2410_GPG6_SPIMOSI1);
+		s3c_gpio_cfgpin(S3C2410_GPG(5), S3C2410_GPG5_SPIMISO1);
 		s3c2410_gpio_pullup(S3C2410_GPG(5), 0);
 		s3c2410_gpio_pullup(S3C2410_GPG(6), 0);
 	} else {
-		s3c2410_gpio_cfgpin(S3C2410_GPG(7), S3C2410_GPIO_INPUT);
-		s3c2410_gpio_cfgpin(S3C2410_GPG(5), S3C2410_GPIO_INPUT);
-		s3c2410_gpio_pullup(S3C2410_GPG(5), 1);
-		s3c2410_gpio_pullup(S3C2410_GPG(6), 1);
-		s3c2410_gpio_pullup(S3C2410_GPG(7), 1);
+		s3c_gpio_cfgpin(S3C2410_GPG(7), S3C2410_GPIO_INPUT);
+		s3c_gpio_cfgpin(S3C2410_GPG(5), S3C2410_GPIO_INPUT);
+		s3c_gpio_cfgpull(S3C2410_GPG(5), S3C_GPIO_PULL_NONE);
+		s3c_gpio_cfgpull(S3C2410_GPG(6), S3C_GPIO_PULL_NONE);
+		s3c_gpio_cfgpull(S3C2410_GPG(7), S3C_GPIO_PULL_NONE);
 	}
 }

+ 104 - 7
arch/arm/plat-samsung/gpio-config.c

@@ -1,7 +1,7 @@
 /* linux/arch/arm/plat-s3c/gpio-config.c
  *
  * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
+ * Copyright 2008-2010 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
  *	http://armlinux.simtec.co.uk/
  *
@@ -33,14 +33,34 @@ int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
 
 	offset = pin - chip->chip.base;
 
-	local_irq_save(flags);
+	s3c_gpio_lock(chip, flags);
 	ret = s3c_gpio_do_setcfg(chip, offset, config);
-	local_irq_restore(flags);
+	s3c_gpio_unlock(chip, flags);
 
 	return ret;
 }
 EXPORT_SYMBOL(s3c_gpio_cfgpin);
 
+unsigned s3c_gpio_getcfg(unsigned int pin)
+{
+	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
+	unsigned long flags;
+	unsigned ret = 0;
+	int offset;
+
+	if (chip) {
+		offset = pin - chip->chip.base;
+
+		s3c_gpio_lock(chip, flags);
+		ret = s3c_gpio_do_getcfg(chip, offset);
+		s3c_gpio_unlock(chip, flags);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(s3c_gpio_getcfg);
+
+
 int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull)
 {
 	struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin);
@@ -52,17 +72,17 @@ int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull)
 
 	offset = pin - chip->chip.base;
 
-	local_irq_save(flags);
+	s3c_gpio_lock(chip, flags);
 	ret = s3c_gpio_do_setpull(chip, offset, pull);
-	local_irq_restore(flags);
+	s3c_gpio_unlock(chip, flags);
 
 	return ret;
 }
 EXPORT_SYMBOL(s3c_gpio_setpull);
 
 #ifdef CONFIG_S3C_GPIO_CFG_S3C24XX
-int s3c_gpio_setcfg_s3c24xx_banka(struct s3c_gpio_chip *chip,
-				  unsigned int off, unsigned int cfg)
+int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
+			      unsigned int off, unsigned int cfg)
 {
 	void __iomem *reg = chip->base;
 	unsigned int shift = off;
@@ -87,6 +107,19 @@ int s3c_gpio_setcfg_s3c24xx_banka(struct s3c_gpio_chip *chip,
 	return 0;
 }
 
+unsigned s3c_gpio_getcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
+				   unsigned int off)
+{
+	u32 con;
+
+	con = __raw_readl(chip->base);
+	con >>= off;
+	con &= 1;
+	con++;
+
+	return S3C_GPIO_SFN(con);
+}
+
 int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip,
 			    unsigned int off, unsigned int cfg)
 {
@@ -109,6 +142,19 @@ int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip,
 
 	return 0;
 }
+
+unsigned int s3c_gpio_getcfg_s3c24xx(struct s3c_gpio_chip *chip,
+				     unsigned int off)
+{
+	u32 con;
+
+	con = __raw_readl(chip->base);
+	con >>= off * 2;
+	con &= 3;
+
+	/* this conversion works for IN and OUT as well as special mode */
+	return S3C_GPIO_SPECIAL(con);
+}
 #endif
 
 #ifdef CONFIG_S3C_GPIO_CFG_S3C64XX
@@ -134,6 +180,25 @@ int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
 
 	return 0;
 }
+
+unsigned s3c_gpio_getcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
+				      unsigned int off)
+{
+	void __iomem *reg = chip->base;
+	unsigned int shift = (off & 7) * 4;
+	u32 con;
+
+	if (off < 8 && chip->chip.ngpio > 8)
+		reg -= 4;
+
+	con = __raw_readl(reg);
+	con >>= shift;
+	con &= 0xf;
+
+	/* this conversion works for IN and OUT as well as special mode */
+	return S3C_GPIO_SPECIAL(con);
+}
+
 #endif /* CONFIG_S3C_GPIO_CFG_S3C64XX */
 
 #ifdef CONFIG_S3C_GPIO_PULL_UPDOWN
@@ -164,3 +229,35 @@ s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip,
 	return (__force s3c_gpio_pull_t)pup;
 }
 #endif
+
+#ifdef CONFIG_S3C_GPIO_PULL_UP
+int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip,
+			 unsigned int off, s3c_gpio_pull_t pull)
+{
+	void __iomem *reg = chip->base + 0x08;
+	u32 pup = __raw_readl(reg);
+
+	pup = __raw_readl(reg);
+
+	if (pup == S3C_GPIO_PULL_UP)
+		pup &= ~(1 << off);
+	else if (pup == S3C_GPIO_PULL_NONE)
+		pup |= (1 << off);
+	else
+		return -EINVAL;
+
+	__raw_writel(pup, reg);
+	return 0;
+}
+
+s3c_gpio_pull_t s3c_gpio_getpull_1up(struct s3c_gpio_chip *chip,
+				     unsigned int off)
+{
+	void __iomem *reg = chip->base + 0x08;
+	u32 pup = __raw_readl(reg);
+
+	pup &= (1 << off);
+	return pup ? S3C_GPIO_PULL_NONE : S3C_GPIO_PULL_UP;
+}
+#endif /* CONFIG_S3C_GPIO_PULL_UP */
+

+ 9 - 6
arch/arm/plat-samsung/gpio.c

@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
+#include <linux/spinlock.h>
 
 #include <plat/gpio-core.h>
 
@@ -52,14 +53,14 @@ static int s3c_gpiolib_input(struct gpio_chip *chip, unsigned offset)
 	unsigned long flags;
 	unsigned long con;
 
-	local_irq_save(flags);
+	s3c_gpio_lock(ourchip, flags);
 
 	con = __raw_readl(base + 0x00);
 	con &= ~(3 << (offset * 2));
 
 	__raw_writel(con, base + 0x00);
 
-	local_irq_restore(flags);
+	s3c_gpio_unlock(ourchip, flags);
 	return 0;
 }
 
@@ -72,7 +73,7 @@ static int s3c_gpiolib_output(struct gpio_chip *chip,
 	unsigned long dat;
 	unsigned long con;
 
-	local_irq_save(flags);
+	s3c_gpio_lock(ourchip, flags);
 
 	dat = __raw_readl(base + 0x04);
 	dat &= ~(1 << offset);
@@ -87,7 +88,7 @@ static int s3c_gpiolib_output(struct gpio_chip *chip,
 	__raw_writel(con, base + 0x00);
 	__raw_writel(dat, base + 0x04);
 
-	local_irq_restore(flags);
+	s3c_gpio_unlock(ourchip, flags);
 	return 0;
 }
 
@@ -99,7 +100,7 @@ static void s3c_gpiolib_set(struct gpio_chip *chip,
 	unsigned long flags;
 	unsigned long dat;
 
-	local_irq_save(flags);
+	s3c_gpio_lock(ourchip, flags);
 
 	dat = __raw_readl(base + 0x04);
 	dat &= ~(1 << offset);
@@ -107,7 +108,7 @@ static void s3c_gpiolib_set(struct gpio_chip *chip,
 		dat |= 1 << offset;
 	__raw_writel(dat, base + 0x04);
 
-	local_irq_restore(flags);
+	s3c_gpio_unlock(ourchip, flags);
 }
 
 static int s3c_gpiolib_get(struct gpio_chip *chip, unsigned offset)
@@ -131,6 +132,8 @@ __init void s3c_gpiolib_add(struct s3c_gpio_chip *chip)
 	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)

+ 58 - 0
arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h

@@ -30,6 +30,12 @@ static inline int s3c_gpio_do_setcfg(struct s3c_gpio_chip *chip,
 	return (chip->config->set_config)(chip, off, config);
 }
 
+static inline unsigned s3c_gpio_do_getcfg(struct s3c_gpio_chip *chip,
+					  unsigned int off)
+{
+	return (chip->config->get_config)(chip, off);
+}
+
 static inline int s3c_gpio_do_setpull(struct s3c_gpio_chip *chip,
 				      unsigned int off, s3c_gpio_pull_t pull)
 {
@@ -52,6 +58,18 @@ static inline int s3c_gpio_do_setpull(struct s3c_gpio_chip *chip,
 extern int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip,
 				   unsigned int off, unsigned int cfg);
 
+/**
+ * s3c_gpio_getcfg_s3c24xx - S3C24XX style GPIO configuration read.
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ *
+ * The reverse of s3c_gpio_setcfg_s3c24xx(). Will return a value whicg
+ * could be directly passed back to s3c_gpio_setcfg_s3c24xx(), from the
+ * S3C_GPIO_SPECIAL() macro.
+ */
+unsigned int s3c_gpio_getcfg_s3c24xx(struct s3c_gpio_chip *chip,
+				     unsigned int off);
+
 /**
  * s3c_gpio_setcfg_s3c24xx_a - S3C24XX style GPIO configuration (Bank A)
  * @chip: The gpio chip that is being configured.
@@ -65,6 +83,21 @@ extern int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip,
 extern int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
 				     unsigned int off, unsigned int cfg);
 
+
+/**
+ * s3c_gpio_getcfg_s3c24xx_a - S3C24XX style GPIO configuration read (Bank A)
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ *
+ * The reverse of s3c_gpio_setcfg_s3c24xx_a() turning an GPIO into a usable
+ * GPIO configuration value.
+ *
+ * @sa s3c_gpio_getcfg_s3c24xx
+ * @sa s3c_gpio_getcfg_s3c64xx_4bit
+ */
+extern unsigned s3c_gpio_getcfg_s3c24xx_a(struct s3c_gpio_chip *chip,
+					  unsigned int off);
+
 /**
  * s3c_gpio_setcfg_s3c64xx_4bit - S3C64XX 4bit single register GPIO config.
  * @chip: The gpio chip that is being configured.
@@ -85,6 +118,20 @@ extern int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
 					unsigned int off, unsigned int cfg);
 
 
+/**
+ * s3c_gpio_getcfg_s3c64xx_4bit - S3C64XX 4bit single register GPIO config read.
+ * @chip: The gpio chip that is being configured.
+ * @off: The offset for the GPIO being configured.
+ *
+ * The reverse of s3c_gpio_setcfg_s3c64xx_4bit(), turning a gpio configuration
+ * register setting into a value the software can use, such as could be passed
+ * to s3c_gpio_setcfg_s3c64xx_4bit().
+ *
+ * @sa s3c_gpio_getcfg_s3c24xx
+ */
+extern unsigned s3c_gpio_getcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,
+					     unsigned int off);
+
 /* Pull-{up,down} resistor controls.
  *
  * S3C2410,S3C2440,S3C24A0 = Pull-UP,
@@ -145,6 +192,17 @@ extern int s3c_gpio_setpull_updown(struct s3c_gpio_chip *chip,
 extern s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip,
 					       unsigned int off);
 
+/**
+ * s3c_gpio_getpull_1up() - Get configuration for choice of up or none
+ * @chip: The gpio chip that the GPIO pin belongs to
+ * @off: The offset to the pin to get the configuration of.
+ *
+ * This helper function reads the state of the pull-up resistor for the
+ * given GPIO in the same case as s3c_gpio_setpull_1up.
+*/
+extern s3c_gpio_pull_t s3c_gpio_getpull_1up(struct s3c_gpio_chip *chip,
+					    unsigned int off);
+
 /**
  * s3c_gpio_setpull_s3c2443() - Pull configuration for s3c2443.
  * @chip: The gpio chip that is being configured.

+ 11 - 0
arch/arm/plat-samsung/include/plat/gpio-cfg.h

@@ -77,6 +77,17 @@ struct s3c_gpio_cfg {
  */
 extern int s3c_gpio_cfgpin(unsigned int pin, unsigned int to);
 
+/**
+ * s3c_gpio_getcfg - Read the current function for a GPIO pin
+ * @pin: The pin to read the configuration value for.
+ *
+ * Read the configuration state of the given @pin, returning a value that
+ * could be passed back to s3c_gpio_cfgpin().
+ *
+ * @sa s3c_gpio_cfgpin
+ */
+extern unsigned s3c_gpio_getcfg(unsigned int pin);
+
 /* Define values for the pull-{up,down} available for each gpio pin.
  *
  * These values control the state of the weak pull-{up,down} resistors

+ 17 - 0
arch/arm/plat-samsung/include/plat/gpio-core.h

@@ -44,16 +44,26 @@ struct s3c_gpio_cfg;
  * @chip: The chip structure to be exported via gpiolib.
  * @base: The base pointer to the gpio configuration registers.
  * @config: special function and pull-resistor control information.
+ * @lock: Lock for exclusive access to this gpio bank.
  * @pm_save: Save information for suspend/resume support.
  *
  * This wrapper provides the necessary information for the Samsung
  * specific gpios being registered with gpiolib.
+ *
+ * The lock protects each gpio bank from multiple access of the shared
+ * configuration registers, or from reading of data whilst another thread
+ * is writing to the register set.
+ *
+ * Each chip has its own lock to avoid any  contention between different
+ * CPU cores trying to get one lock for different GPIO banks, where each
+ * bank of GPIO has its own register space and configuration registers.
  */
 struct s3c_gpio_chip {
 	struct gpio_chip	chip;
 	struct s3c_gpio_cfg	*config;
 	struct s3c_gpio_pm	*pm;
 	void __iomem		*base;
+	spinlock_t		 lock;
 #ifdef CONFIG_PM
 	u32			pm_save[4];
 #endif
@@ -108,6 +118,9 @@ extern void samsung_gpiolib_add_4bit2_chips(struct s3c_gpio_chip *chip,
 extern void samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip);
 extern void samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip);
 
+/* exported for core SoC support to change */
+extern struct s3c_gpio_cfg s3c24xx_gpiocfg_default;
+
 #ifdef CONFIG_S3C_GPIO_TRACK
 extern struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END];
 
@@ -135,3 +148,7 @@ extern struct s3c_gpio_pm s3c_gpio_pm_4bit;
 #define __gpio_pm(x) NULL
 
 #endif /* CONFIG_PM */
+
+/* locking wrappers to deal with multiple access to the same gpio bank */
+#define s3c_gpio_lock(_oc, _fl) spin_lock_irqsave(&(_oc)->lock, _fl)
+#define s3c_gpio_unlock(_oc, _fl) spin_unlock_irqrestore(&(_oc)->lock, _fl)

+ 2 - 2
arch/arm/plat-samsung/pm-gpio.c

@@ -329,7 +329,7 @@ void s3c_pm_save_gpios(void)
 	struct s3c_gpio_chip *ourchip;
 	unsigned int gpio_nr;
 
-	for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) {
+	for (gpio_nr = 0; gpio_nr < S3C_GPIO_END;) {
 		ourchip = s3c_gpiolib_getchip(gpio_nr);
 		if (!ourchip)
 			continue;
@@ -367,7 +367,7 @@ void s3c_pm_restore_gpios(void)
 	struct s3c_gpio_chip *ourchip;
 	unsigned int gpio_nr;
 
-	for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) {
+	for (gpio_nr = 0; gpio_nr < S3C_GPIO_END;) {
 		ourchip = s3c_gpiolib_getchip(gpio_nr);
 		if (!ourchip)
 			continue;