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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
|
From d74710dd508eb1b60b410048a151e1d541d749d2 Mon Sep 17 00:00:00 2001
From: Andy Green <andy@openmoko.com>
Date: Fri, 25 Jul 2008 23:06:15 +0100
Subject: [PATCH] fix-pcf50633-migrate-gta02-peripherals-out.patch
pcf50633.c shouldn't know GTAxx at all. Move to using a
platform callback to allow definition of platform devices
with pcf50633 as parent device (good for enforcing suspend /
resume ordering). Remove all code references to GTAxx from
the sources (one string left for compatability).
Signed-off-by: Andy Green <andy@openmoko.com>
---
arch/arm/mach-s3c2440/mach-gta02.c | 30 ++++++++++++++++++-
drivers/i2c/chips/pcf50633.c | 57 ++++++++++++++++++-----------------
include/linux/pcf50633.h | 9 +++++-
3 files changed, 66 insertions(+), 30 deletions(-)
diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
index 309e484..fd746fd 100644
--- a/arch/arm/mach-s3c2440/mach-gta02.c
+++ b/arch/arm/mach-s3c2440/mach-gta02.c
@@ -464,6 +464,29 @@ static int pmu_callback(struct device *dev, unsigned int feature,
return 0;
}
+static struct platform_device gta01_pm_gps_dev = {
+ .name = "neo1973-pm-gps",
+};
+
+static struct platform_device gta01_pm_bt_dev = {
+ .name = "neo1973-pm-bt",
+};
+
+/* this is called when pc50633 is probed, unfortunately quite late in the
+ * day since it is an I2C bus device. Here we can belatedly define some
+ * platform devices with the advantage that we can mark the pcf50633 as the
+ * parent. This makes them get suspended and resumed with their parent
+ * the pcf50633 still around.
+ */
+
+static void gta02_pcf50633_attach_child_devices(struct device *parent_device)
+{
+ gta01_pm_gps_dev.dev.parent = parent_device;
+ gta01_pm_bt_dev.dev.parent = parent_device;
+ platform_device_register(>a01_pm_bt_dev);
+ platform_device_register(>a01_pm_gps_dev);
+}
+
static struct pcf50633_platform_data gta02_pcf_pdata = {
.used_features = PCF50633_FEAT_MBC |
PCF50633_FEAT_BBC |
@@ -478,6 +501,7 @@ static struct pcf50633_platform_data gta02_pcf_pdata = {
.r_fix_batt = 10000,
.r_fix_batt_par = 10000,
.r_sense_milli = 220,
+ .flag_use_apm_emulation = 0,
.resumers = {
[0] = PCF50633_INT1_USBINS |
PCF50633_INT1_USBREM |
@@ -577,7 +601,9 @@ static struct pcf50633_platform_data gta02_pcf_pdata = {
},
},
.defer_resume_backlight = 1,
- .resume_backlight_ramp_speed = 5
+ .resume_backlight_ramp_speed = 5,
+ .attach_child_devices = gta02_pcf50633_attach_child_devices
+
};
#if 0 /* currently unused */
@@ -772,6 +798,7 @@ struct platform_device s3c24xx_pwm_device = {
.num_resources = 0,
};
+
static struct platform_device *gta02_devices[] __initdata = {
&s3c_device_usb,
&s3c_device_wdt,
@@ -786,6 +813,7 @@ static struct platform_device *gta02_devices[] __initdata = {
>a02_version_device,
>a02_resume_reason_device,
&s3c24xx_pwm_device,
+
};
static struct s3c2410_nand_set gta02_nand_sets[] = {
diff --git a/drivers/i2c/chips/pcf50633.c b/drivers/i2c/chips/pcf50633.c
index 6745993..850bf93 100644
--- a/drivers/i2c/chips/pcf50633.c
+++ b/drivers/i2c/chips/pcf50633.c
@@ -50,7 +50,6 @@
#include <linux/jiffies.h>
#include <asm/mach-types.h>
-#include <asm/arch/gta02.h>
#include "pcf50633.h"
#include <linux/resume-dependency.h>
@@ -2004,18 +2003,6 @@ static DEVICE_ATTR(dump_regs, 0400, show_dump_regs, NULL);
* Driver initialization
***********************************************************************/
-#ifdef CONFIG_MACH_NEO1973_GTA02
-/* We currently place those platform devices here to make sure the device
- * suspend/resume order is correct */
-static struct platform_device gta01_pm_gps_dev = {
- .name = "neo1973-pm-gps",
-};
-
-static struct platform_device gta01_pm_bt_dev = {
- .name = "neo1973-pm-bt",
-};
-#endif
-
/*
* CARE! This table is modified at runtime!
*/
@@ -2209,14 +2196,15 @@ static int pcf50633_detect(struct i2c_adapter *adapter, int address, int kind)
apm_get_power_status = pcf50633_get_power_status;
data->probe_completed = 1;
-#ifdef CONFIG_MACH_NEO1973_GTA02
- if (machine_is_neo1973_gta02()) {
- gta01_pm_gps_dev.dev.parent = &new_client->dev;
- gta01_pm_bt_dev.dev.parent = &new_client->dev;
- platform_device_register(>a01_pm_bt_dev);
- platform_device_register(>a01_pm_gps_dev);
- }
-#endif
+ if (data->pdata->flag_use_apm_emulation)
+ apm_get_power_status = pcf50633_get_power_status;
+
+ /* if platform was interested, give him a chance to register
+ * platform devices that switch power with us as the parent
+ * at registration time -- ensures suspend / resume ordering
+ */
+ if (data->pdata->attach_child_devices)
+ (data->pdata->attach_child_devices)(&new_client->dev);
return 0;
exit_rtc:
@@ -2261,13 +2249,6 @@ static int pcf50633_detach_client(struct i2c_client *client)
if (pcf->pdata->used_features & PCF50633_FEAT_RTC)
rtc_device_unregister(pcf->rtc);
-#ifdef CONFIG_MACH_NEO1973_GTA02
- if (machine_is_neo1973_gta02()) {
- platform_device_unregister(>a01_pm_bt_dev);
- platform_device_unregister(>a01_pm_gps_dev);
- }
-#endif
-
sysfs_remove_group(&client->dev.kobj, &pcf_attr_group);
pm_power_off = NULL;
@@ -2465,6 +2446,26 @@ int pcf50633_ready(struct pcf50633_data *pcf)
}
EXPORT_SYMBOL_GPL(pcf50633_ready);
+int pcf50633_wait_for_ready(struct pcf50633_data *pcf, int timeout_ms,
+ char *name)
+{
+ /* so we always go once */
+ timeout_ms += 5;
+
+ while ((timeout_ms >= 5) && (pcf50633_ready(pcf))) {
+ timeout_ms -= 5; /* well, it isn't very accurate, but OK */
+ msleep(5);
+ }
+
+ if (timeout_ms < 5) {
+ printk(KERN_ERR"pcf50633_wait_for_ready: "
+ "%s BAILING on timeout\n", name);
+ return -EBUSY;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pcf50633_wait_for_ready);
/*
* if backlight resume is selected to be deferred by platform, then it
diff --git a/include/linux/pcf50633.h b/include/linux/pcf50633.h
index b94b72a..4653285 100644
--- a/include/linux/pcf50633.h
+++ b/include/linux/pcf50633.h
@@ -132,7 +132,9 @@ pcf50633_register_resume_dependency(struct pcf50633_data *pcf,
extern int
pcf50633_notify_usb_current_limit_change(struct pcf50633_data *pcf,
unsigned int ma);
-
+extern int
+pcf50633_wait_for_ready(struct pcf50633_data *pcf, int timeout_ms,
+ char *name);
/* 0 = initialized and resumed and ready to roll, !=0 = either not
* initialized or not resumed yet
@@ -155,6 +157,10 @@ struct pcf50633_platform_data {
unsigned int onkey_seconds_sig_init;
unsigned int onkey_seconds_shutdown;
+ /* callback to attach platform children (to enforce suspend / resume
+ * ordering */
+ void (*attach_child_devices)(struct device *parent_device);
+
/* voltage regulator related */
struct pmu_voltage_rail rails[__NUM_PCF50633_REGULATORS];
unsigned int used_regulators;
@@ -163,6 +169,7 @@ struct pcf50633_platform_data {
unsigned int r_fix_batt;
unsigned int r_fix_batt_par;
unsigned int r_sense_milli;
+ int flag_use_apm_emulation;
unsigned char resumers[5];
--
1.5.6.3
|