[ar71xx] preliminary support for the Ubiquiti RouterStation Pro
[openwrt.git] / target / linux / s3c24xx / patches-2.6.24 / 1242-fix-bq27000-charger-state-tracking.patch.patch
1 From 46159c9a3fba291d106625092fd62358548894e0 Mon Sep 17 00:00:00 2001
2 From: Andy Green <andy@openmoko.com>
3 Date: Tue, 22 Jul 2008 13:16:16 +0100
4 Subject: [PATCH] fix-bq27000-charger-state-tracking.patch
5
6 Charger trigger stuff goes and asks for POWER_SUPPLY_PROP_STATUS
7 to figure out what the charger state is. But until now, we only
8 reported there what we found out from HDQ, and the HDQ registers
9 are not updated very often in the coulomb counter, it can be 4
10 or more second lag before it tells us about what it experiences.
11
12 When we react to USB insertion and only after 500ms debounce tell
13 power_supply stuff that something changed, it most times will
14 see old pre-USB-insertion state from bq27000 over HDQ at that time
15 and will report it ain't charging, buggering up the LED trigger
16 tracking.
17
18 This patch maintains distance between bq27000 and pcf50633 by
19 having platform callbacks in bq27000 that it can use to ask about
20 definitive charger "online" presence and "activity", whether the
21 charger says it is charging. If these callbacks are implemented
22 (and we implement them in this patch up in mach_gta02.c) then
23 this information is used in preference to what is found from
24 HDQ.
25
26 Result is if you set the LED trigger like this:
27
28 echo bat-charging > /sys/devices/platform/gta02-led.0/leds/gta02-aux:red/trigger
29
30 then it lights up properly on USB insertion now, goes away on
31 removal properly, as as far as I saw, when charging stops too.
32
33 Signed-off-by: Andy Green <andy@openmoko.com>
34 ---
35 arch/arm/mach-s3c2440/mach-gta02.c | 32 +++++++++++++++--
36 drivers/power/bq27000_battery.c | 65 ++++++++++++++++++++++++-----------
37 include/linux/bq27000_battery.h | 2 +
38 3 files changed, 74 insertions(+), 25 deletions(-)
39
40 diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
41 index 59ba890..1fcd3fd 100644
42 --- a/arch/arm/mach-s3c2440/mach-gta02.c
43 +++ b/arch/arm/mach-s3c2440/mach-gta02.c
44 @@ -96,6 +96,9 @@ struct resume_dependency resume_dep_jbt_glamo;
45 struct resume_dependency resume_dep_glamo_mci_pcf;
46
47
48 +static int gta02_charger_online_status;
49 +static int gta02_charger_active_status;
50 +
51 /* define FIQ IPC struct */
52 /*
53 * contains stuff FIQ ISR modifies and normal kernel code can see and use
54 @@ -457,12 +460,25 @@ static struct s3c2410_uartcfg gta02_uartcfgs[] = {
55
56 /* BQ27000 Battery */
57
58 +static int gta02_get_charger_online_status(void)
59 +{
60 + return gta02_charger_online_status;
61 +}
62 +
63 +static int gta02_get_charger_active_status(void)
64 +{
65 + return gta02_charger_active_status;
66 +}
67 +
68 +
69 struct bq27000_platform_data bq27000_pdata = {
70 .name = "bat",
71 .rsense_mohms = 20,
72 .hdq_read = gta02hdq_read,
73 .hdq_write = gta02hdq_write,
74 .hdq_initialized = gta02hdq_initialized,
75 + .get_charger_online_status = gta02_get_charger_online_status,
76 + .get_charger_active_status = gta02_get_charger_active_status
77 };
78
79 struct platform_device bq27000_battery_device = {
80 @@ -481,12 +497,20 @@ static int pmu_callback(struct device *dev, unsigned int feature,
81 switch (feature) {
82 case PCF50633_FEAT_MBC:
83 switch (event) {
84 - case PMU_EVT_USB_INSERT:
85 - case PMU_EVT_USB_REMOVE:
86 case PMU_EVT_CHARGER_IDLE:
87 + gta02_charger_active_status = 0;
88 + break;
89 case PMU_EVT_CHARGER_ACTIVE:
90 - case PMU_EVT_INSERT: /* adapter */
91 - case PMU_EVT_REMOVE: /* adapter */
92 + gta02_charger_active_status = 1;
93 + break;
94 + case PMU_EVT_USB_INSERT:
95 + gta02_charger_online_status = 1;
96 + break;
97 + case PMU_EVT_USB_REMOVE:
98 + gta02_charger_online_status = 0;
99 + break;
100 + case PMU_EVT_INSERT: /* adapter is unsused */
101 + case PMU_EVT_REMOVE: /* adapter is unused */
102 break;
103 default:
104 break;
105 diff --git a/drivers/power/bq27000_battery.c b/drivers/power/bq27000_battery.c
106 index 4855d5a..7020608 100644
107 --- a/drivers/power/bq27000_battery.c
108 +++ b/drivers/power/bq27000_battery.c
109 @@ -113,12 +113,7 @@ enum bq27000_status_flags {
110 struct bq27000_device_info {
111 struct device *dev;
112 struct power_supply bat;
113 -
114 - int rsense_mohms; /* from platform */
115 -
116 - int (*hdq_initialized)(void); /* from platform */
117 - int (*hdq_read)(int); /* from platform */
118 - int (*hdq_write)(int, u8); /* from platform */
119 + struct bq27000_platform_data *pdata;
120 };
121
122 /*
123 @@ -136,16 +131,16 @@ static int hdq_read16(struct bq27000_device_info *di, int address)
124
125 while (retries--) {
126
127 - high = (di->hdq_read)(address + 1); /* high part */
128 + high = (di->pdata->hdq_read)(address + 1); /* high part */
129
130 if (high < 0)
131 return high;
132 - acc = (di->hdq_read)(address);
133 + acc = (di->pdata->hdq_read)(address);
134 if (acc < 0)
135 return acc;
136
137 /* confirm high didn't change between reading it and low */
138 - if (high == (di->hdq_read)(address + 1))
139 + if (high == (di->pdata->hdq_read)(address + 1))
140 return (high << 8) | acc;
141 }
142
143 @@ -170,12 +165,36 @@ static int bq27000_battery_get_property(struct power_supply *psy,
144 int v, n;
145 struct bq27000_device_info *di = to_bq27000_device_info(psy);
146
147 - if (!(di->hdq_initialized)())
148 + if (!(di->pdata->hdq_initialized)())
149 return -EINVAL;
150
151 switch (psp) {
152 case POWER_SUPPLY_PROP_STATUS:
153 val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
154 +
155 + if (!di->pdata->get_charger_online_status)
156 + goto use_bat;
157 + if ((di->pdata->get_charger_online_status)()) {
158 + /*
159 + * charger is definitively present
160 + * we report our state in terms of what it says it
161 + * is doing
162 + */
163 + if (!di->pdata->get_charger_active_status)
164 + goto use_bat;
165 + if ((di->pdata->get_charger_active_status)())
166 + val->intval = POWER_SUPPLY_STATUS_CHARGING;
167 + else
168 + val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
169 + break;
170 + }
171 +use_bat:
172 + /*
173 + * either the charger is not connected, or the
174 + * platform doesn't give info about charger, use battery state
175 + * but... battery state can be out of date by 4 seconds or
176 + * so... use the platform callbacks if possible.
177 + */
178 v = hdq_read16(di, BQ27000_AI_L);
179 if (v < 0)
180 return v;
181 @@ -189,7 +208,7 @@ static int bq27000_battery_get_property(struct power_supply *psy,
182 break;
183 }
184 /* power is actually going in or out... */
185 - v = (di->hdq_read)(BQ27000_FLAGS);
186 + v = (di->pdata->hdq_read)(BQ27000_FLAGS);
187 if (v < 0)
188 return v;
189 if (v & BQ27000_STATUS_CHGS)
190 @@ -205,7 +224,7 @@ static int bq27000_battery_get_property(struct power_supply *psy,
191 val->intval = v * 1000;
192 break;
193 case POWER_SUPPLY_PROP_CURRENT_NOW:
194 - v = (di->hdq_read)(BQ27000_FLAGS);
195 + v = (di->pdata->hdq_read)(BQ27000_FLAGS);
196 if (v < 0)
197 return v;
198 if (v & BQ27000_STATUS_CHGS)
199 @@ -215,13 +234,13 @@ static int bq27000_battery_get_property(struct power_supply *psy,
200 v = hdq_read16(di, BQ27000_AI_L);
201 if (v < 0)
202 return v;
203 - val->intval = (v * n) / di->rsense_mohms;
204 + val->intval = (v * n) / di->pdata->rsense_mohms;
205 break;
206 case POWER_SUPPLY_PROP_CHARGE_FULL:
207 v = hdq_read16(di, BQ27000_LMD_L);
208 if (v < 0)
209 return v;
210 - val->intval = (v * 3570) / di->rsense_mohms;
211 + val->intval = (v * 3570) / di->pdata->rsense_mohms;
212 break;
213 case POWER_SUPPLY_PROP_TEMP:
214 v = hdq_read16(di, BQ27000_TEMP_L);
215 @@ -235,12 +254,12 @@ static int bq27000_battery_get_property(struct power_supply *psy,
216 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
217 break;
218 case POWER_SUPPLY_PROP_CAPACITY:
219 - val->intval = (di->hdq_read)(BQ27000_RSOC);
220 + val->intval = (di->pdata->hdq_read)(BQ27000_RSOC);
221 if (val->intval < 0)
222 return val->intval;
223 break;
224 case POWER_SUPPLY_PROP_PRESENT:
225 - v = (di->hdq_read)(BQ27000_RSOC);
226 + v = (di->pdata->hdq_read)(BQ27000_RSOC);
227 val->intval = !(v < 0);
228 break;
229 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
230 @@ -255,6 +274,12 @@ static int bq27000_battery_get_property(struct power_supply *psy,
231 return v;
232 val->intval = 60 * v;
233 break;
234 + case POWER_SUPPLY_PROP_ONLINE:
235 + if (di->pdata->get_charger_online_status)
236 + val->intval = (di->pdata->get_charger_online_status)();
237 + else
238 + return -EINVAL;
239 + break;
240 default:
241 return -EINVAL;
242 }
243 @@ -272,7 +297,8 @@ static enum power_supply_property bq27000_battery_props[] = {
244 POWER_SUPPLY_PROP_PRESENT,
245 POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
246 POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
247 - POWER_SUPPLY_PROP_CAPACITY
248 + POWER_SUPPLY_PROP_CAPACITY,
249 + POWER_SUPPLY_PROP_ONLINE
250 };
251
252 static int bq27000_battery_probe(struct platform_device *pdev)
253 @@ -302,10 +328,7 @@ static int bq27000_battery_probe(struct platform_device *pdev)
254 di->bat.external_power_changed =
255 bq27000_battery_external_power_changed;
256 di->bat.use_for_apm = 1;
257 - di->hdq_read = pdata->hdq_read;
258 - di->hdq_write = pdata->hdq_write;
259 - di->rsense_mohms = pdata->rsense_mohms;
260 - di->hdq_initialized = pdata->hdq_initialized;
261 + di->pdata = pdata;
262
263 retval = power_supply_register(&pdev->dev, &di->bat);
264 if (retval) {
265 diff --git a/include/linux/bq27000_battery.h b/include/linux/bq27000_battery.h
266 index fed4287..a617466 100644
267 --- a/include/linux/bq27000_battery.h
268 +++ b/include/linux/bq27000_battery.h
269 @@ -9,6 +9,8 @@ struct bq27000_platform_data {
270 int (*hdq_read)(int);
271 int (*hdq_write)(int, u8);
272 int (*hdq_initialized)(void);
273 + int (*get_charger_online_status)(void);
274 + int (*get_charger_active_status)(void);
275 };
276
277 #endif
278 --
279 1.5.6.5
280
This page took 0.074452 seconds and 5 git commands to generate.