[PATCH 1/1] Add Minimal GSM flowcontrol functionality

Mike (mwester) mwester at dls.net
Fri Aug 8 06:03:03 CEST 2008


This is version 4 of this patch at this point, and
obsoletes all other versions of this patch (including
the version that seems to have erroneously slipped onto
the debug branch in the git repo).

The operative word in this patch description is "minimal";
this patch requires (unlike previous versions) a cooperative
user-space application that is "in charge" of suspend/resume
in order to be useful.  The standard "apmd" with scripts is
suitable for images that use apm to manage suspend/resume;
other images will require code changes to gain any benefit
from this patch.

Also note that the GTA01 requires additional changes that
are no longer part of this patch.

The above changes seem to be necessary to get the change
committed to stable; we can work on putting back some of the
missing functionality in later.

Mike (mwester)

(As noted by the date below, this patch has been around
and well tested by now -- it will apply to stable, with some
noise about offsets while patching.)

-----------------------------

commit 088101571660b85bb7e6073e0da5fcbdbbd9aa87
Author: Mike Westerhof <mwester at dls.net>
Date:   Fri Jul 4 13:53:46 2008 -0500

    Add the basic GSM flowcontrol code.

    Signed-off-by: Mike Westerhof <mwester at dls.net>

diff --git a/arch/arm/mach-s3c2410/mach-gta01.c b/arch/arm/mach-s3c2410/mach-gta01.c
index 6af5566..a017328 100644
--- a/arch/arm/mach-s3c2410/mach-gta01.c
+++ b/arch/arm/mach-s3c2410/mach-gta01.c
@@ -652,9 +652,12 @@ static void __init gta01_map_io(void)
        s3c24xx_init_uarts(gta01_uartcfgs, ARRAY_SIZE(gta01_uartcfgs));
 }

+extern int gta_gsm_interrupts;
+
 static irqreturn_t gta01_modem_irq(int irq, void *param)
 {
        printk(KERN_DEBUG "GSM wakeup interrupt (IRQ %d)\n", irq);
+       gta_gsm_interrupts++;
        return IRQ_HANDLED;
 }

diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
index 7118332..6876850 100644
--- a/arch/arm/mach-s3c2440/mach-gta02.c
+++ b/arch/arm/mach-s3c2440/mach-gta02.c
@@ -1492,9 +1492,12 @@ static void __init gta02_map_io(void)
        s3c24xx_init_uarts(gta02_uartcfgs, ARRAY_SIZE(gta02_uartcfgs));
 }

+extern int gta_gsm_interrupts;
+
 static irqreturn_t gta02_modem_irq(int irq, void *param)
 {
        printk(KERN_DEBUG "modem wakeup interrupt\n");
+       gta_gsm_interrupts++;
        return IRQ_HANDLED;
 }

diff --git a/arch/arm/plat-s3c24xx/neo1973_pm_gsm.c b/arch/arm/plat-s3c24xx/neo1973_pm_gsm.c
index 5ef23d1..178c9f7 100644
--- a/arch/arm/plat-s3c24xx/neo1973_pm_gsm.c
+++ b/arch/arm/plat-s3c24xx/neo1973_pm_gsm.c
@@ -34,6 +34,9 @@
 extern void s3c24xx_serial_register_resume_dependency(struct resume_dependency *
                                             resume_dependency, int uart_index);

+int gta_gsm_interrupts;
+EXPORT_SYMBOL(gta_gsm_interrupts);
+
 struct gta01pm_priv {
        int gpio_ngsm_en;
         int gpio_ndl_gsm;
@@ -80,6 +83,9 @@ static ssize_t gsm_read(struct device *dev, struct device_attribute *attr,
                        if (!s3c2410_gpio_getpin(GTA02_GPIO_nDL_GSM))
                                goto out_1;
                }
+       } else if (!strcmp(attr->attr.name, "flowcontrolled")) {
+               if (s3c2410_gpio_getcfg(S3C2410_GPH1) == S3C2410_GPIO_OUTPUT)
+                       goto out_1;
        }

        return strlcpy(buf, "0\n", 3);
@@ -176,6 +182,13 @@ static ssize_t gsm_write(struct device *dev, struct device_attribute *attr,
                        gta01_gsm.gpio_ndl_gsm = !on;
                        s3c2410_gpio_setpin(GTA02_GPIO_nDL_GSM, !on);
                }
+       } else if (!strcmp(attr->attr.name, "flowcontrolled")) {
+               if (on) {
+                       gta_gsm_interrupts = 0;
+                       s3c2410_gpio_setpin(S3C2410_GPH1, 1);
+                       s3c2410_gpio_cfgpin(S3C2410_GPH1, S3C2410_GPH1_OUTP);
+               } else
+                       s3c2410_gpio_cfgpin(S3C2410_GPH1, S3C2410_GPH1_nRTS0);
        }

        return count;
@@ -184,6 +197,7 @@ static ssize_t gsm_write(struct device *dev, struct device_attribute *attr,
 static DEVICE_ATTR(power_on, 0644, gsm_read, gsm_write);
 static DEVICE_ATTR(reset, 0644, gsm_read, gsm_write);
 static DEVICE_ATTR(download, 0644, gsm_read, gsm_write);
+static DEVICE_ATTR(flowcontrolled, 0644, gsm_read, gsm_write);

 #ifdef CONFIG_PM
 static int gta01_gsm_resume(struct platform_device *pdev);
@@ -192,6 +206,11 @@ static int gta01_gsm_suspend(struct platform_device *pdev, pm_message_t state)
        /* GPIO state is saved/restored by S3C2410 core GPIO driver, so we
         * don't need to do much here. */

+       /* If flowcontrol asserted, abort if GSM already interrupted */
+       if (s3c2410_gpio_getcfg(S3C2410_GPH1) == S3C2410_GPIO_OUTPUT) {
+               if (gta_gsm_interrupts)
+                       goto busy;
+       }

        /* disable DL GSM to prevent jack_insert becoming 'floating' */
        if (machine_is_neo1973_gta02())
@@ -204,6 +223,20 @@ static int gta01_gsm_suspend(struct platform_device *pdev, pm_message_t state)
        s3c24xx_serial_register_resume_dependency(&resume_dep_gsm_uart, 0);

        return 0;
+
+busy:
+       return -EBUSY;
+}
+
+static int
+gta01_gsm_suspend_late(struct platform_device *pdev, pm_message_t state)
+{
+       /* Last chance: abort if GSM already interrupted */
+       if (s3c2410_gpio_getcfg(S3C2410_GPH1) == S3C2410_GPIO_OUTPUT) {
+               if (gta_gsm_interrupts)
+                       return -EBUSY;
+       }
+       return 0;
 }

 static int gta01_gsm_resume(struct platform_device *pdev)
@@ -228,6 +261,7 @@ static int gta01_gsm_resume(struct platform_device *pdev)
 }
 #else
 #define gta01_gsm_suspend      NULL
+#define gta01_gsm_suspend_late NULL
 #define gta01_gsm_resume       NULL
 #endif

@@ -235,6 +269,7 @@ static struct attribute *gta01_gsm_sysfs_entries[] = {
        &dev_attr_power_on.attr,
        &dev_attr_reset.attr,
        &dev_attr_download.attr,
+       &dev_attr_flowcontrolled.attr,
        NULL
 };

@@ -314,6 +349,7 @@ static struct platform_driver gta01_gsm_driver = {
        .probe          = gta01_gsm_probe,
        .remove         = gta01_gsm_remove,
        .suspend        = gta01_gsm_suspend,
+       .suspend_late   = gta01_gsm_suspend_late,
        .resume         = gta01_gsm_resume,
        .driver         = {
                .name           = "neo1973-pm-gsm",




More information about the openmoko-kernel mailing list