[PATCH] Accessing GPIO GPB_XY and not losing the LED state

Holger Freyther zecke at openmoko.org
Wed Apr 9 23:55:59 CEST 2008


Hey,

the three LEDs are connected directly to the base of the transistor. So even 
while the GPIO Bank B is input/output we can not expect to read anything sane 
on the three LED pins. This means any usage of s3c2410_gpio_setpin will 
disable the LEDs when they were on, this includes the vibrator, the modem, 
the gps (on GTA01).

The only way I saw to get something reliable is to keep track of the state in 
the kernel, I didn't really consider putting this code in the gpio_setpin 
implementation, so I added my own set of setter methods. This means any write 
access to GPB must go through these new setters.

So is the approach sane, implementation as well, comments?


The gta01 has no LEDs so is not subject to this issue, I was not sure if I 
should update the code. I decided to do so. In the files shared by 
gta01/gta02 it makes it look consistent, I even did it for the rest of the 
gta01 code, it does not hurt, is consistent...


From d6edf1716a6d041f90d00202bfddad4687355968 Mon Sep 17 00:00:00 2001
From: Holger Freyther <zecke at openmoko.org>
Date: Wed, 9 Apr 2008 22:16:37 +0200
Subject: [PATCH] [neo] Every access to GPIO bank B has to go through the 
shadow code

    - Any setting of any PIN on bank B will undo the LED setting.
      Introduce neo1973_gpb_set_pin to set the PIN in a way not losing
      the LED or any other shadowed setting.
    - Update users of GPBXY for gta01 and gta02
    - Fix the gsm reset handling: GTA01_GPIO_MODEM_RST != GTA02_GPIO_MODEM_RST
---
 arch/arm/mach-s3c2410/mach-gta01.c     |    9 ++--
 arch/arm/mach-s3c2440/mach-gta02.c     |   10 ++--
 arch/arm/plat-s3c24xx/Makefile         |    4 +-
 arch/arm/plat-s3c24xx/neo1973_pm_bt.c  |   15 +++---
 arch/arm/plat-s3c24xx/neo1973_pm_gps.c |    5 ++-
 arch/arm/plat-s3c24xx/neo1973_pm_gsm.c |   22 +++++++--
 arch/arm/plat-s3c24xx/neo1973_shadow.c |   84 
++++++++++++++++++++++++++++++++
 drivers/leds/leds-neo1973-gta02.c      |   55 ++-------------------
 drivers/leds/leds-neo1973-vibrator.c   |   10 +++-
 drivers/video/backlight/gta01_bl.c     |    9 ++--
 include/asm-arm/plat-s3c24xx/neo1973.h |   33 ++++++++++++
 11 files changed, 178 insertions(+), 78 deletions(-)
 create mode 100644 arch/arm/plat-s3c24xx/neo1973_shadow.c
 create mode 100644 include/asm-arm/plat-s3c24xx/neo1973.h

diff --git a/arch/arm/mach-s3c2410/mach-gta01.c 
b/arch/arm/mach-s3c2410/mach-gta01.c
index 8c1a402..bf99b8a 100644
--- a/arch/arm/mach-s3c2410/mach-gta01.c
+++ b/arch/arm/mach-s3c2410/mach-gta01.c
@@ -72,6 +72,7 @@
 #include <asm/plat-s3c24xx/cpu.h>
 #include <asm/plat-s3c24xx/pm.h>
 #include <asm/plat-s3c24xx/udc.h>
+#include <asm/plat-s3c24xx/neo1973.h>
 
 static struct map_desc gta01_iodesc[] __initdata = {
 	{
@@ -416,10 +417,10 @@ static void gta01_mmc_set_power(unsigned char 
power_mode, unsigned short vdd)
 	case GTA01Bv4_SYSTEM_REV:
 		switch (power_mode) {
 		case MMC_POWER_OFF:
-			s3c2410_gpio_setpin(GTA01_GPIO_SDMMC_ON, 1);
+			neo1973_gpb_set_pin(GTA01_GPIO_SDMMC_ON, 1);
 			break;
 		case MMC_POWER_ON:
-			s3c2410_gpio_setpin(GTA01_GPIO_SDMMC_ON, 0);
+			neo1973_gpb_set_pin(GTA01_GPIO_SDMMC_ON, 0);
 			break;
 		}
 		break;
@@ -442,10 +443,10 @@ static void gta01_udc_command(enum s3c2410_udc_cmd_e 
cmd)
 
 	switch (cmd) {
 	case S3C2410_UDC_P_ENABLE:
-		s3c2410_gpio_setpin(GTA01_GPIO_USB_PULLUP, 1);
+		neo1973_gpb_set_pin(GTA01_GPIO_USB_PULLUP, 1);
 		break;
 	case S3C2410_UDC_P_DISABLE:
-		s3c2410_gpio_setpin(GTA01_GPIO_USB_PULLUP, 0);
+		neo1973_gpb_set_pin(GTA01_GPIO_USB_PULLUP, 0);
 		break;
 	default:
 		break;
diff --git a/arch/arm/mach-s3c2440/mach-gta02.c 
b/arch/arm/mach-s3c2440/mach-gta02.c
index 320e511..c5359aa 100644
--- a/arch/arm/mach-s3c2440/mach-gta02.c
+++ b/arch/arm/mach-s3c2440/mach-gta02.c
@@ -75,6 +75,7 @@
 #include <asm/plat-s3c24xx/cpu.h>
 #include <asm/plat-s3c24xx/pm.h>
 #include <asm/plat-s3c24xx/udc.h>
+#include <asm/plat-s3c24xx/neo1973.h>
 #include <linux/jbt6k74.h>
 
 #include <linux/glamofb.h>
@@ -127,11 +128,11 @@ FIQ_HANDLER_ENTRY(256, 512)
 
 	if (fiq_ipc.vib_pwm_latched || fiq_ipc.vib_pwm) { /* not idle */
 		if (((u8)_fiq_count_fiqs) == fiq_ipc.vib_pwm_latched)
-			s3c2410_gpio_setpin(fiq_ipc.vib_gpio_pin, 0);
+			neo1973_gpb_set_pin(fiq_ipc.vib_gpio_pin, 0);
 		if (((u8)_fiq_count_fiqs) == 0) {
 			fiq_ipc.vib_pwm_latched = fiq_ipc.vib_pwm;
 			if (fiq_ipc.vib_pwm_latched)
-				s3c2410_gpio_setpin(fiq_ipc.vib_gpio_pin, 1);
+				neo1973_gpb_set_pin(fiq_ipc.vib_gpio_pin, 1);
 		}
 		divisor = FIQ_DIVISOR_VIBRATOR;
 	}
@@ -319,6 +320,7 @@ FIQ_HANDLER_ENTRY(256, 512)
 FIQ_HANDLER_END()
 
 
+
 /**
  * returns PCB revision information in b9,b8 and b2,b1,b0
  * Pre-GTA02 A6 returns 0x000
@@ -762,10 +764,10 @@ static void gta02_udc_command(enum s3c2410_udc_cmd_e 
cmd)
 
 	switch (cmd) {
 	case S3C2410_UDC_P_ENABLE:
-		s3c2410_gpio_setpin(GTA02_GPIO_USB_PULLUP, 1);
+		neo1973_gpb_set_pin(GTA02_GPIO_USB_PULLUP, 1);
 		break;
 	case S3C2410_UDC_P_DISABLE:
-		s3c2410_gpio_setpin(GTA02_GPIO_USB_PULLUP, 0);
+		neo1973_gpb_set_pin(GTA02_GPIO_USB_PULLUP, 0);
 		break;
 	case S3C2410_UDC_P_RESET:
 		/* FIXME! */
diff --git a/arch/arm/plat-s3c24xx/Makefile b/arch/arm/plat-s3c24xx/Makefile
index e667105..0efcc15 100644
--- a/arch/arm/plat-s3c24xx/Makefile
+++ b/arch/arm/plat-s3c24xx/Makefile
@@ -32,4 +32,6 @@ obj-$(CONFIG_MACH_NEO1973)	+= neo1973_version.o \
 				   neo1973_pm_host.o \
 				   neo1973_pm_gsm.o \
 				   neo1973_pm_gps.o \
-				   neo1973_pm_bt.o
+				   neo1973_pm_bt.o  \
+				   neo1973_shadow.o
+
diff --git a/arch/arm/plat-s3c24xx/neo1973_pm_bt.c 
b/arch/arm/plat-s3c24xx/neo1973_pm_bt.c
index a9694b4..5985ef4 100644
--- a/arch/arm/plat-s3c24xx/neo1973_pm_bt.c
+++ b/arch/arm/plat-s3c24xx/neo1973_pm_bt.c
@@ -18,6 +18,7 @@
 
 #include <asm/hardware.h>
 #include <asm/mach-types.h>
+#include <asm/plat-s3c24xx/neo1973.h>
 
 #ifdef CONFIG_MACH_NEO1973_GTA01
 #include <asm/arch/gta01.h>
@@ -95,20 +96,20 @@ static ssize_t bt_write(struct device *dev, struct 
device_attribute *attr,
 			/* if we are powering up, assert reset, then power,
 			 * then release reset */
 			if (on) {
-				s3c2410_gpio_setpin(GTA01_GPIO_BT_EN, 0);
+				neo1973_gpb_set_pin(GTA01_GPIO_BT_EN, 0);
 				pcf50606_voltage_set(pcf50606_global,
 						     PCF50606_REGULATOR_D1REG,
 						     3100);
 			}
 			pcf50606_onoff_set(pcf50606_global,
 					   PCF50606_REGULATOR_D1REG, on);
-			s3c2410_gpio_setpin(GTA01_GPIO_BT_EN, on);
+			neo1973_gpb_set_pin(GTA01_GPIO_BT_EN, on);
 			break;
 #endif /* CONFIG_MACH_NEO1973_GTA01 */
 
 #ifdef CONFIG_MACH_NEO1973_GTA02
 		case MACH_TYPE_NEO1973_GTA02:
-			s3c2410_gpio_setpin(GTA02_GPIO_BT_EN, on ? 0 : 1);
+			neo1973_gpb_set_pin(GTA02_GPIO_BT_EN, on ? 0 : 1);
 			if (on)
 				pcf50633_voltage_set(pcf50633_global,
 					PCF50633_REGULATOR_LDO4, 3200);
@@ -127,13 +128,13 @@ static ssize_t bt_write(struct device *dev, struct 
device_attribute *attr,
 
 #ifdef CONFIG_MACH_NEO1973_GTA01
 		case MACH_TYPE_NEO1973_GTA01:
-			s3c2410_gpio_setpin(GTA01_GPIO_BT_EN, on ? 0 : 1);
+			neo1973_gpb_set_pin(GTA01_GPIO_BT_EN, on ? 0 : 1);
 			break;
 #endif /* CONFIG_MACH_NEO1973_GTA01 */
 
 #ifdef CONFIG_MACH_NEO1973_GTA02
 		case MACH_TYPE_NEO1973_GTA02:
-			s3c2410_gpio_setpin(GTA02_GPIO_BT_EN, on ? 0 : 1);
+			neo1973_gpb_set_pin(GTA02_GPIO_BT_EN, on ? 0 : 1);
 			break;
 #endif /* CONFIG_MACH_NEO1973_GTA02 */
 
@@ -192,7 +193,7 @@ static int __init gta01_bt_probe(struct platform_device 
*pdev)
 				   PCF50606_REGULATOR_D1REG, 0);
 		/* we pull reset to low to make sure that the chip doesn't
 	 	 * drain power through the reset line */
-		s3c2410_gpio_setpin(GTA01_GPIO_BT_EN, 0);
+		neo1973_gpb_set_pin(GTA01_GPIO_BT_EN, 0);
 		break;
 #endif /* CONFIG_MACH_NEO1973_GTA01 */
 
@@ -203,7 +204,7 @@ static int __init gta01_bt_probe(struct platform_device 
*pdev)
 				     PCF50633_REGULATOR_LDO4, 0);
 		/* we pull reset to low to make sure that the chip doesn't
 	 	 * drain power through the reset line */
-		s3c2410_gpio_setpin(GTA02_GPIO_BT_EN, 0);
+		neo1973_gpb_set_pin(GTA02_GPIO_BT_EN, 0);
 		break;
 #endif /* CONFIG_MACH_NEO1973_GTA02 */
 
diff --git a/arch/arm/plat-s3c24xx/neo1973_pm_gps.c 
b/arch/arm/plat-s3c24xx/neo1973_pm_gps.c
index 90330a9..081aee7 100644
--- a/arch/arm/plat-s3c24xx/neo1973_pm_gps.c
+++ b/arch/arm/plat-s3c24xx/neo1973_pm_gps.c
@@ -20,6 +20,9 @@
 #include <asm/hardware.h>
 
 #include <asm/mach-types.h>
+
+#include <asm/plat-s3c24xx/neo1973.h>
+
 #ifdef CONFIG_MACH_NEO1973_GTA01
 #include <asm/arch/gta01.h>
 #include <linux/pcf50606.h>
@@ -264,7 +267,7 @@ static void gps_pwron_set(int on)
 {
 #ifdef CONFIG_MACH_NEO1973_GTA01
 	if (machine_is_neo1973_gta01())
-		s3c2410_gpio_setpin(GTA01_GPIO_GPS_PWRON, on);
+		neo1973_gpb_set_pin(GTA01_GPIO_GPS_PWRON, on);
 #endif /* CONFIG_MACH_NEO1973_GTA01 */
 
 #ifdef CONFIG_MACH_NEO1973_GTA02
diff --git a/arch/arm/plat-s3c24xx/neo1973_pm_gsm.c 
b/arch/arm/plat-s3c24xx/neo1973_pm_gsm.c
index 8abc3ef..77288bd 100644
--- a/arch/arm/plat-s3c24xx/neo1973_pm_gsm.c
+++ b/arch/arm/plat-s3c24xx/neo1973_pm_gsm.c
@@ -22,6 +22,7 @@
 #include <asm/gpio.h>
 #include <asm/mach-types.h>
 #include <asm/arch/gta01.h>
+#include <asm/plat-s3c24xx/neo1973.h>
 
 #ifdef CONFIG_MACH_NEO1973_GTA02
 #include <asm/arch/gta02.h>
@@ -60,8 +61,14 @@ static ssize_t gsm_read(struct device *dev, struct 
device_attribute *attr,
 		if (s3c2410_gpio_getpin(GTA01_GPIO_MODEM_ON))
 			goto out_1;
 	} else if (!strcmp(attr->attr.name, "reset")) {
-		if (s3c2410_gpio_getpin(GTA01_GPIO_MODEM_RST))
+#ifdef CONFIG_MACH_NEO1973_GTA01
+		if (machine_is_neo1973_gta01() && 
s3c2410_gpio_getpin(GTA01_GPIO_MODEM_RST))
+			goto out_1;
+#endif
+#ifdef CONFIG_MACH_NEO1973_GTA02
+		if (machine_is_neo1973_gta02() && 
s3c2410_gpio_getpin(GTA02_GPIO_MODEM_RST))
 			goto out_1;
+#endif
 	} else if (!strcmp(attr->attr.name, "download")) {
 #ifdef CONFIG_MACH_NEO1973_GTA01
 		if (machine_is_neo1973_gta01())
@@ -109,9 +116,9 @@ static ssize_t gsm_write(struct device *dev, struct 
device_attribute *attr,
 #endif
 			}
 
-			s3c2410_gpio_setpin(GTA01_GPIO_MODEM_ON, 1);
+			neo1973_gpb_set_pin(GTA01_GPIO_MODEM_ON, 1);
 		} else {
-			s3c2410_gpio_setpin(GTA01_GPIO_MODEM_ON, 0);
+			neo1973_gpb_set_pin(GTA01_GPIO_MODEM_ON, 0);
 
 			switch (system_rev) {
 #ifdef CONFIG_MACH_NEO1973_GTA02
@@ -136,7 +143,14 @@ static ssize_t gsm_write(struct device *dev, struct 
device_attribute *attr,
 			}
 		}
 	} else if (!strcmp(attr->attr.name, "reset")) {
-		s3c2410_gpio_setpin(GTA01_GPIO_MODEM_RST, on);
+#ifdef CONFIG_MACH_NEO1973_GTA01
+		if (machine_is_neo1973_gta01())
+			neo1973_gpb_set_pin(GTA01_GPIO_MODEM_RST, on);
+#endif
+#ifdef CONFIG_MACH_NEO1973_GTA02
+		if (machine_is_neo1973_gta02())
+			neo1973_gpb_set_pin(GTA02_GPIO_MODEM_RST, on);
+#endif
 	} else if (!strcmp(attr->attr.name, "download")) {
 #ifdef CONFIG_MACH_NEO1973_GTA01
 		if (machine_is_neo1973_gta01())
diff --git a/arch/arm/plat-s3c24xx/neo1973_shadow.c 
b/arch/arm/plat-s3c24xx/neo1973_shadow.c
new file mode 100644
index 0000000..2e9c377
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/neo1973_shadow.c
@@ -0,0 +1,84 @@
+/*
+ * include/asm-arm/plat-s3c24xx/neo1973.h
+ *
+ * Common utility code for GTA01 and GTA02
+ *
+ * Copyright (C) 2008 by Openmoko, Inc.
+ * Author: Holger Hans Peter Freyther <freyther at openmoko.org>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <linux/io.h>
+#include <linux/irq.h>
+
+#include <asm/gpio.h>
+#include <asm/plat-s3c24xx/neo1973.h>
+
+/**
+ * Shadow GPIO bank B handling. For the LEDs we need to keep track of the 
state
+ * in software. The s3c2410_gpio_setpin must not be used for GPIOs on bank B
+ */
+static unsigned long gpb_mask;
+static unsigned long gpb_state;
+
+void neo1973_gpb_add_shadow_gpio(unsigned int gpio)
+{
+	unsigned long offset = S3C2410_GPIO_OFFSET(gpio);
+	unsigned long flags;
+
+	local_irq_save(flags);
+	gpb_mask |= 1L << offset;
+	local_irq_restore(flags);
+}
+EXPORT_SYMBOL(neo1973_gpb_add_shadow_gpio);
+
+static void set_shadow_gpio(unsigned long offset, unsigned int value)
+{
+	unsigned long state = value != 0;
+
+	gpb_state &= ~(1L << offset);
+	gpb_state |= state << offset;
+}
+
+void neo1973_gpb_set_pin(unsigned int pin, unsigned to)
+{
+	void __iomem *base = S3C24XX_GPIO_BASE(S3C2410_GPB0);
+	unsigned long offset = S3C2410_GPIO_OFFSET(pin);
+	unsigned long flags;
+	unsigned long dat;
+
+	local_irq_save(flags);
+	dat = __raw_readl(base + 0x04);
+
+	/* Add the shadow values */
+	dat &= ~gpb_mask;
+	dat |= gpb_state;
+
+	/* Do the operation like s3c2410_gpio_setpin */
+	dat &= ~(1L << offset);
+	dat |= to << offset;
+
+	/* Update the shadow state */
+	if ((1L << offset) & gpb_mask)
+		set_shadow_gpio(offset, to);
+
+	__raw_writel(dat, base + 0x04);
+	local_irq_restore(flags);
+}
+EXPORT_SYMBOL(neo1973_gpb_set_pin);
diff --git a/drivers/leds/leds-neo1973-gta02.c 
b/drivers/leds/leds-neo1973-gta02.c
index df0a1f7..29ddcfe 100644
--- a/drivers/leds/leds-neo1973-gta02.c
+++ b/drivers/leds/leds-neo1973-gta02.c
@@ -20,6 +20,7 @@
 #include <asm/arch/pwm.h>
 #include <asm/arch/gta02.h>
 #include <asm/plat-s3c/regs-timer.h>
+#include <asm/plat-s3c24xx/neo1973.h>
 
 #define MAX_LEDS 3
 #define COUNTER 256
@@ -35,10 +36,7 @@ struct gta02_led_priv
 
 struct gta02_led_bundle
 {
-	struct mutex mutex;
 	int num_leds;
-	unsigned long gpio_mask;
-	unsigned long gpio_state;
 	struct gta02_led_priv led[MAX_LEDS];
 };
 
@@ -52,39 +50,6 @@ static inline struct gta02_led_bundle *to_bundle(struct 
led_classdev *led_cdev)
 	return dev_get_drvdata(led_cdev->dev->parent);
 }
 
-static void gta02led_bundle_update(struct gta02_led_bundle *bundle)
-{
-	/* we know the LEDs are on bank B */
-	void __iomem *base = S3C24XX_GPIO_BASE(S3C2410_GPB0);
-	unsigned long flags;
-	unsigned long dat;
-
-	mutex_lock(&bundle->mutex);
-
-	local_irq_save(flags);
-	dat = __raw_readl(base + 0x04);
-	dat &= ~bundle->gpio_mask;
-	dat |= bundle->gpio_state;
-	__raw_writel(dat, base + 0x04);
-	local_irq_restore(flags);
-
-	mutex_unlock(&bundle->mutex);
-}
-
-static void gta02led_bundle_set(struct gta02_led_bundle *bundle, int gpio, 
int value)
-{
-	unsigned long offset = S3C2410_GPIO_OFFSET(gpio);
-	unsigned long state = value != 0;
-
-	mutex_lock(&bundle->mutex);
-
-	bundle->gpio_state &= ~(1L << offset);
-	bundle->gpio_state |= state << offset;
-
-	mutex_unlock(&bundle->mutex);
-}
-
-
 static void gta02led_set(struct led_classdev *led_cdev,
 		enum led_brightness value)
 {
@@ -100,8 +65,7 @@ static void gta02led_set(struct led_classdev *led_cdev,
 	if (lp->has_pwm) {
 		s3c2410_pwm_duty_cycle(value, &lp->pwm);
 	} else {
-		gta02led_bundle_set(to_bundle(led_cdev), lp->gpio, value);
-		gta02led_bundle_update(to_bundle(led_cdev));
+		neo1973_gpb_set_pin(lp->gpio, value ? 1 : 0);
 	}
 
 	mutex_unlock(&lp->mutex);
@@ -142,13 +106,11 @@ static int __init gta02led_probe(struct platform_device 
*pdev)
 	bundle = kzalloc(sizeof(struct gta02_led_bundle), GFP_KERNEL);
 	if (!bundle)
 		return -ENOMEM;
-	mutex_init(&bundle->mutex);
 	platform_set_drvdata(pdev, bundle);
 
 	for (i = 0; i < pdev->num_resources; i++) {
 		struct gta02_led_priv *lp;
 		struct resource *r;
-		unsigned long offset;
 
 		if (i >= MAX_LEDS)
 			break;
@@ -202,10 +164,7 @@ static int __init gta02led_probe(struct platform_device 
*pdev)
 		case S3C2410_GPB3:
 			lp->has_pwm = 0;
 			s3c2410_gpio_cfgpin(lp->gpio, S3C2410_GPIO_OUTPUT);
-
-			offset = S3C2410_GPIO_OFFSET(lp->gpio);
-			bundle->gpio_mask |= 1L << offset;
-			gta02led_bundle_set(bundle, lp->gpio, 0);
+			neo1973_gpb_add_shadow_gpio(lp->gpio);
 			break;
 		default:
 			break;
@@ -216,7 +175,6 @@ static int __init gta02led_probe(struct platform_device 
*pdev)
 	}
 
 	bundle->num_leds = i;
-	gta02led_bundle_update(bundle);
 
 	return 0;
 }
@@ -230,17 +188,14 @@ static int gta02led_remove(struct platform_device *pdev)
 		struct gta02_led_priv *lp = &bundle->led[i];
 		if (lp->has_pwm)
 			s3c2410_pwm_disable(&lp->pwm);
+		else
+			gta02led_set(&lp->cdev, 0);
 
 		led_classdev_unregister(&lp->cdev);
 		mutex_destroy(&lp->mutex);
 	}
 
-	/* turn off the leds */
-	bundle->gpio_state = 0;
-	gta02led_bundle_update(bundle);
-
 	platform_set_drvdata(pdev, NULL);
-	mutex_destroy(&bundle->mutex);
 	kfree(bundle);
 
 	return 0;
diff --git a/drivers/leds/leds-neo1973-vibrator.c 
b/drivers/leds/leds-neo1973-vibrator.c
index f31302d..141444b 100644
--- a/drivers/leds/leds-neo1973-vibrator.c
+++ b/drivers/leds/leds-neo1973-vibrator.c
@@ -24,6 +24,7 @@
 #include <asm/plat-s3c/regs-timer.h>
 
 #include <asm/arch-s3c2410/fiq_ipc_gta02.h>
+#include <asm/plat-s3c24xx/neo1973.h>
 
 #define COUNTER 64
 
@@ -56,9 +57,9 @@ static void neo1973_vib_vib_set(struct led_classdev 
*led_cdev,
 		s3c2410_pwm_duty_cycle(value / 4, &vp->pwm);
 	else {
 		if (value)
-			s3c2410_gpio_setpin(vp->gpio, 1);
+			neo1973_gpb_set_pin(vp->gpio, 1);
 		else
-			s3c2410_gpio_setpin(vp->gpio, 0);
+			neo1973_gpb_set_pin(vp->gpio, 0);
 	}
 
 	mutex_unlock(&vp->mutex);
@@ -131,7 +132,7 @@ static int __init neo1973_vib_probe(struct platform_device 
*pdev)
 	platform_set_drvdata(pdev, &neo1973_vib_led);
 
 	if (machine_is_neo1973_gta02()) { /* use FIQ to control GPIO */
-		s3c2410_gpio_setpin(neo1973_vib_led.gpio, 0); /* off */
+		neo1973_gpb_set_pin(neo1973_vib_led.gpio, 0); /* off */
 		s3c2410_gpio_cfgpin(neo1973_vib_led.gpio, S3C2410_GPIO_OUTPUT);
 		/* safe, kmalloc'd copy needed for FIQ ISR */
 		fiq_ipc.vib_gpio_pin = neo1973_vib_led.gpio;
@@ -149,6 +150,9 @@ static int __init neo1973_vib_probe(struct platform_device 
*pdev)
 		s3c2410_gpio_cfgpin(neo1973_vib_led.gpio, S3C2410_GPB3_TOUT3);
 		neo1973_vib_led.has_pwm = 1;
 	}
+
+	if (!neo1973_vib_led.has_pwm)
+		neo1973_gpb_add_shadow_gpio(neo1973_vib_led.gpio);
 configured:
 	mutex_init(&neo1973_vib_led.mutex);
 
diff --git a/drivers/video/backlight/gta01_bl.c 
b/drivers/video/backlight/gta01_bl.c
index bd7d41f..d6463bd 100644
--- a/drivers/video/backlight/gta01_bl.c
+++ b/drivers/video/backlight/gta01_bl.c
@@ -40,6 +40,7 @@
 #include <asm/arch/pwm.h>
 
 #include <asm/plat-s3c/regs-timer.h>
+#include <asm/plat-s3c24xx/neo1973.h>
 
 static struct backlight_properties gta01bl_prop;
 static struct backlight_device *gta01_backlight_device;
@@ -83,12 +84,12 @@ static int gta01bl_send_intensity(struct backlight_device 
*bd)
 	mutex_lock(&gta01bl.mutex);
 #ifdef GTA01_BACKLIGHT_ONOFF_ONLY
 	if (intensity)
-		s3c2410_gpio_setpin(GTA01_GPIO_BACKLIGHT, 1);
+		neo1973_gpb_set_pin(GTA01_GPIO_BACKLIGHT, 1);
 	else
-		s3c2410_gpio_setpin(GTA01_GPIO_BACKLIGHT, 0);
+		neo1973_gpb_set_pin(GTA01_GPIO_BACKLIGHT, 0);
 #else
 	if (intensity == bd->props.max_brightness) {
-		s3c2410_gpio_setpin(GTA01_GPIO_BACKLIGHT, 1);
+		neo1973_gpb_set_pin(GTA01_GPIO_BACKLIGHT, 1);
 		s3c2410_gpio_cfgpin(GTA01_GPIO_BACKLIGHT, S3C2410_GPIO_OUTPUT);
 	} else  {
 		s3c2410_pwm_duty_cycle(intensity & 0xffff, &gta01bl.pwm);
@@ -222,7 +223,7 @@ static int gta01bl_remove(struct platform_device *dev)
 	mutex_destroy(&gta01bl.mutex);
 
 	s3c2410_gpio_cfgpin(GTA01_GPIO_BACKLIGHT, S3C2410_GPIO_OUTPUT);
-	s3c2410_gpio_setpin(GTA01_GPIO_BACKLIGHT, 1);
+	neo1973_gpb_set_pin(GTA01_GPIO_BACKLIGHT, 1);
 
 	return 0;
 }
diff --git a/include/asm-arm/plat-s3c24xx/neo1973.h 
b/include/asm-arm/plat-s3c24xx/neo1973.h
new file mode 100644
index 0000000..9cc36b8
--- /dev/null
+++ b/include/asm-arm/plat-s3c24xx/neo1973.h
@@ -0,0 +1,33 @@
+/*
+ * include/asm-arm/plat-s3c24xx/neo1973.h
+ *
+ * Common utility code for GTA01 and GTA02
+ *
+ * Copyright (C) 2008 by Openmoko, Inc.
+ * Author: Holger Hans Peter Freyther <freyther at openmoko.org>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#ifndef NEO1973_H
+#define NEO1973_H
+
+void neo1973_gpb_add_shadow_gpio(unsigned int gpio);
+void neo1973_gpb_set_pin(unsigned int pin, unsigned to);
+
+#endif
-- 
1.5.3





More information about the openmoko-kernel mailing list