summaryrefslogtreecommitdiff
path: root/target/linux/s3c24xx/patches-2.6.26/0240-gta0x-add-minimal-GSM-flowcontrol.patch.patch
blob: e3e3c571de876bf94b651555c9b72af7cda3c18a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
From 5a0021aed270b0d98a902d9c8eb19b395dc186ae Mon Sep 17 00:00:00 2001
From: Mike Westerhof <mwester@dls.net>
Date: Sun, 10 Aug 2008 09:12:55 +0100
Subject: [PATCH] gta0x-add-minimal-GSM-flowcontrol.patch

    Add the basic GSM flowcontrol code.

Signed-off-by: Mike Westerhof <mwester@dls.net>
---
 arch/arm/mach-s3c2410/mach-gta01.c     |    3 ++
 arch/arm/mach-s3c2440/mach-gta02.c     |    3 ++
 arch/arm/plat-s3c24xx/neo1973_pm_gsm.c |   36 ++++++++++++++++++++++++++++++++
 3 files changed, 42 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-s3c2410/mach-gta01.c b/arch/arm/mach-s3c2410/mach-gta01.c
index e518de7..f3f87cf 100644
--- a/arch/arm/mach-s3c2410/mach-gta01.c
+++ b/arch/arm/mach-s3c2410/mach-gta01.c
@@ -657,9 +657,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 aeedd42..b37d1c4 100644
--- a/arch/arm/mach-s3c2440/mach-gta02.c
+++ b/arch/arm/mach-s3c2440/mach-gta02.c
@@ -1531,9 +1531,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 de83939..901f8fb 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
 
@@ -193,6 +207,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())
@@ -205,6 +224,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)
@@ -229,6 +262,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
 
@@ -236,6 +270,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
 };
 
@@ -315,6 +350,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",
-- 
1.5.6.3