aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/s3c24xx/patches-2.6.24/1212-fix-gsm-resume-problems.patch.patch
blob: 8c6d68e35320e6468978a8f97ad49661c3f46ba4 (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
From 2a1042fc56273fac721207597968af313751c17b Mon Sep 17 00:00:00 2001
From: Andy Green <andy@openmoko.com>
Date: Wed, 2 Jul 2008 22:43:53 +0100
Subject: [PATCH] fix-gsm-resume-problems.patch

Signed-off-by: Andy Green <andy@openmoko.com>
---
 arch/arm/plat-s3c24xx/neo1973_pm_gsm.c |   32 ++++++++++++++++++++++++++++++++
 drivers/serial/s3c2410.c               |   17 +++++++++++++++++
 2 files changed, 49 insertions(+), 0 deletions(-)

diff --git a/arch/arm/plat-s3c24xx/neo1973_pm_gsm.c b/arch/arm/plat-s3c24xx/neo1973_pm_gsm.c
index 149b866..d70a481 100644
--- a/arch/arm/plat-s3c24xx/neo1973_pm_gsm.c
+++ b/arch/arm/plat-s3c24xx/neo1973_pm_gsm.c
@@ -18,6 +18,7 @@
 #include <linux/console.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
+#include <linux/resume-dependency.h>
 
 #include <asm/gpio.h>
 #include <asm/mach-types.h>
@@ -33,9 +34,12 @@
 struct gta01pm_priv {
 	int gpio_ngsm_en;
         int gpio_ndl_gsm;
+
 	struct console *con;
 };
 
+struct resume_dependency resume_dep_gsm_uart;
+
 static struct gta01pm_priv gta01_gsm;
 
 static struct console *find_s3c24xx_console(void)
@@ -179,6 +183,21 @@ static DEVICE_ATTR(reset, 0644, gsm_read, gsm_write);
 static DEVICE_ATTR(download, 0644, gsm_read, gsm_write);
 
 #ifdef CONFIG_PM
+static void gsm_resume_work(struct work_struct *w)
+{
+	printk(KERN_INFO "%s: waiting...\n", __FUNCTION__);
+	if (gsm_autounlock_delay)
+		msleep(gsm_autounlock_delay);
+	if (gsm_auto_flowcontrolled) {
+		if (machine_is_neo1973_gta01())
+			s3c24xx_fake_rx_interrupt(10000);
+		s3c2410_gpio_cfgpin(S3C2410_GPH1, S3C2410_GPH1_nRTS0);
+		gsm_auto_flowcontrolled = 0;
+	}
+	printk(KERN_INFO "%s: done.\n", __FUNCTION__);
+}
+
+static int gta01_gsm_resume(struct platform_device *pdev);
 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
@@ -189,11 +208,22 @@ static int gta01_gsm_suspend(struct platform_device *pdev, pm_message_t state)
 	if (machine_is_neo1973_gta02())
 		s3c2410_gpio_setpin(GTA02_GPIO_nDL_GSM, 1);
 
+	/* register our resume dependency on the appropriate UART being up */
+	resume_dep_gsm_uart.callback = gta01_gsm_resume;
+	resume_dep_gsm_uart.context = (void *)pdev;
+
+	s3c24xx_serial_register_resume_dependency(&resume_dep_gsm_uart, 0);
+
 	return 0;
 }
 
 static int gta01_gsm_resume(struct platform_device *pdev)
 {
+	if (resume_dep_gsm_uart.called_flag != 1)
+		return 0;
+
+	resume_dep_gsm_uart.called_flag++; /* only run once */
+
 	/* GPIO state is saved/restored by S3C2410 core GPIO driver, so we
 	 * don't need to do much here. */
 
@@ -279,6 +309,8 @@ static int __init gta01_gsm_probe(struct platform_device *pdev)
 	if (machine_is_neo1973_gta02())
 		s3c2410_gpio_setpin(GTA02_GPIO_nDL_GSM, 1);
 
+	init_resume_dependency_list(&resume_dep_gsm_uart);
+
 	return sysfs_create_group(&pdev->dev.kobj, &gta01_gsm_attr_group);
 }
 
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
index b566f42..bc6736d 100644
--- a/drivers/serial/s3c2410.c
+++ b/drivers/serial/s3c2410.c
@@ -72,6 +72,7 @@
 #include <linux/serial.h>
 #include <linux/delay.h>
 #include <linux/clk.h>
+#include <linux/resume-dependency.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -112,6 +113,8 @@ struct s3c24xx_uart_port {
 	struct clk			*clk;
 	struct clk			*baudclk;
 	struct uart_port		port;
+
+	struct resume_dependency	resume_dependency;
 };
 
 
@@ -1085,6 +1088,8 @@ static int s3c24xx_serial_probe(struct platform_device *dev,
 	ourport = &s3c24xx_serial_ports[probe_index];
 	probe_index++;
 
+	init_resume_dependency_list(&ourport->resume_dependency);
+
 	dbg("%s: initialising port %p...\n", __FUNCTION__, ourport);
 
 	ret = s3c24xx_serial_init_port(ourport, info, dev);
@@ -1125,6 +1130,16 @@ static int s3c24xx_serial_suspend(struct platform_device *dev, pm_message_t stat
 	return 0;
 }
 
+void s3c24xx_serial_register_resume_dependency(struct resume_dependency *
+					      resume_dependency, int uart_index)
+{
+	struct s3c24xx_uart_port *ourport = &s3c24xx_serial_ports[uart_index];
+
+	register_resume_dependency(&ourport->resume_dependency,
+							     resume_dependency);
+}
+EXPORT_SYMBOL(s3c24xx_serial_register_resume_dependency);
+
 static int s3c24xx_serial_resume(struct platform_device *dev)
 {
 	struct uart_port *port = s3c24xx_dev_to_port(&dev->dev);
@@ -1138,6 +1153,8 @@ static int s3c24xx_serial_resume(struct platform_device *dev)
 		uart_resume_port(&s3c24xx_uart_drv, port);
 	}
 
+	callback_all_resume_dependencies(&ourport->resume_dependency);
+
 	return 0;
 }
 
-- 
1.5.6.5