aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorHolger Freyther <zecke@openmoko.org>2008-11-19 17:09:38 +0000
committerAndy Green <agreen@pads.home.warmcat.com>2008-11-19 17:09:38 +0000
commitab0a466054d12647d906cf3a9ac9cb19cbd7607b (patch)
tree28270cfdc9a73ac7c42ea52f6e15e352d9577933 /arch
parent77739f17fbae2718f4de551969e5c3b47b041978 (diff)
[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. Signed-Off-By: Holger Freyther <zecke@openmoko.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-s3c2410/mach-gta01.c9
-rw-r--r--arch/arm/mach-s3c2440/mach-gta02.c10
-rw-r--r--arch/arm/plat-s3c24xx/Makefile4
-rw-r--r--arch/arm/plat-s3c24xx/neo1973_pm_bt.c15
-rw-r--r--arch/arm/plat-s3c24xx/neo1973_pm_gps.c5
-rw-r--r--arch/arm/plat-s3c24xx/neo1973_pm_gsm.c9
-rw-r--r--arch/arm/plat-s3c24xx/neo1973_shadow.c86
7 files changed, 117 insertions, 21 deletions
diff --git a/arch/arm/mach-s3c2410/mach-gta01.c b/arch/arm/mach-s3c2410/mach-gta01.c
index 8c1a4026660..a4384b694db 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_setpin(GTA01_GPIO_SDMMC_ON, 1);
break;
case MMC_POWER_ON:
- s3c2410_gpio_setpin(GTA01_GPIO_SDMMC_ON, 0);
+ neo1973_gpb_setpin(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_setpin(GTA01_GPIO_USB_PULLUP, 1);
break;
case S3C2410_UDC_P_DISABLE:
- s3c2410_gpio_setpin(GTA01_GPIO_USB_PULLUP, 0);
+ neo1973_gpb_setpin(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 f9e00d5194e..27babc9f968 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_setpin(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_setpin(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
@@ -763,10 +765,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_setpin(GTA02_GPIO_USB_PULLUP, 1);
break;
case S3C2410_UDC_P_DISABLE:
- s3c2410_gpio_setpin(GTA02_GPIO_USB_PULLUP, 0);
+ neo1973_gpb_setpin(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 cf78e07528e..40de6052b89 100644
--- a/arch/arm/plat-s3c24xx/Makefile
+++ b/arch/arm/plat-s3c24xx/Makefile
@@ -47,4 +47,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 a9694b4c1c4..dfc9ae8e9f4 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_setpin(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_setpin(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_setpin(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_setpin(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_setpin(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_setpin(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_setpin(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 d882f7b0231..d020f8d4843 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_setpin(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 5ad942eb3a0..149b8669add 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>
@@ -109,9 +110,9 @@ static ssize_t gsm_write(struct device *dev, struct device_attribute *attr,
#endif
}
- s3c2410_gpio_setpin(GTA01_GPIO_MODEM_ON, 1);
+ neo1973_gpb_setpin(GTA01_GPIO_MODEM_ON, 1);
} else {
- s3c2410_gpio_setpin(GTA01_GPIO_MODEM_ON, 0);
+ neo1973_gpb_setpin(GTA01_GPIO_MODEM_ON, 0);
switch (system_rev) {
#ifdef CONFIG_MACH_NEO1973_GTA02
@@ -138,9 +139,9 @@ static ssize_t gsm_write(struct device *dev, struct device_attribute *attr,
}
} else if (!strcmp(attr->attr.name, "reset")) {
if (machine_is_neo1973_gta01())
- s3c2410_gpio_setpin(GTA01_GPIO_MODEM_RST, on);
+ neo1973_gpb_setpin(GTA01_GPIO_MODEM_RST, on);
else if (machine_is_neo1973_gta02())
- s3c2410_gpio_setpin(GTA02_GPIO_MODEM_RST, on);
+ neo1973_gpb_setpin(GTA02_GPIO_MODEM_RST, on);
} else if (!strcmp(attr->attr.name, "download")) {
if (machine_is_neo1973_gta01())
s3c2410_gpio_setpin(GTA01_GPIO_MODEM_DNLOAD, on);
diff --git a/arch/arm/plat-s3c24xx/neo1973_shadow.c b/arch/arm/plat-s3c24xx/neo1973_shadow.c
new file mode 100644
index 00000000000..09667da312b
--- /dev/null
+++ b/arch/arm/plat-s3c24xx/neo1973_shadow.c
@@ -0,0 +1,86 @@
+/*
+ * 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@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_setpin(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;
+
+ BUG_ON(base != S3C24XX_GPIO_BASE(pin));
+
+ 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_setpin);