changed Makefile and profiles, added patches for kernel 2.6.24
[openwrt.git] / target / linux / s3c24xx / patches-2.6.26 / 0219-fix-bq27000-charger-state-tracking.patch.patch
1 From 40023f1501f3cd5ec55739b3142e9e45a67bb735 Mon Sep 17 00:00:00 2001
2 From: Andy Green <andy@openmoko.com>
3 Date: Fri, 25 Jul 2008 23:06:20 +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    |   66 ++++++++++++++++++++++++-----------
37  include/linux/bq27000_battery.h    |    2 +
38  3 files changed, 73 insertions(+), 27 deletions(-)
39
40 diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
41 index f30abb6..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,16 +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_INSERT:
85 +               case PMU_EVT_CHARGER_IDLE:
86 +                       gta02_charger_active_status = 0;
87 +                       break;
88 +               case PMU_EVT_CHARGER_ACTIVE:
89 +                       gta02_charger_active_status = 1;
90 +                       break;
91                 case PMU_EVT_USB_INSERT:
92 -                       pcf50633_charge_enable(pcf50633_global, 1);
93 +                       gta02_charger_online_status = 1;
94                         break;
95 -               case PMU_EVT_REMOVE:
96                 case PMU_EVT_USB_REMOVE:
97 -                       pcf50633_charge_enable(pcf50633_global, 0);
98 +                       gta02_charger_online_status = 0;
99                         break;
100 -               case PMU_EVT_CHARGER_IDLE:
101 -               case PMU_EVT_CHARGER_ACTIVE:
102 +               case PMU_EVT_INSERT: /* adapter is unsused */
103 +               case PMU_EVT_REMOVE: /* adapter is unused */
104                         break;
105                 default:
106                         break;
107 diff --git a/drivers/power/bq27000_battery.c b/drivers/power/bq27000_battery.c
108 index 5598568..7020608 100644
109 --- a/drivers/power/bq27000_battery.c
110 +++ b/drivers/power/bq27000_battery.c
111 @@ -113,12 +113,7 @@ enum bq27000_status_flags {
112  struct bq27000_device_info {
113         struct device *dev;
114         struct power_supply bat;
115 -
116 -       int rsense_mohms;               /* from platform */
117 -
118 -       int (*hdq_initialized)(void); /* from platform */
119 -       int (*hdq_read)(int); /* from platform */
120 -       int (*hdq_write)(int, u8); /* from platform */
121 +       struct bq27000_platform_data *pdata;
122  };
123  
124  /*
125 @@ -136,16 +131,16 @@ static int hdq_read16(struct bq27000_device_info *di, int address)
126  
127         while (retries--) {
128  
129 -               high = (di->hdq_read)(address + 1); /* high part */
130 +               high = (di->pdata->hdq_read)(address + 1); /* high part */
131  
132                 if (high < 0)
133                         return high;
134 -               acc = (di->hdq_read)(address);
135 +               acc = (di->pdata->hdq_read)(address);
136                 if (acc < 0)
137                         return acc;
138  
139                 /* confirm high didn't change between reading it and low */
140 -               if (high == (di->hdq_read)(address + 1))
141 +               if (high == (di->pdata->hdq_read)(address + 1))
142                         return (high << 8) | acc;
143         }
144  
145 @@ -170,12 +165,36 @@ static int bq27000_battery_get_property(struct power_supply *psy,
146         int v, n;
147         struct bq27000_device_info *di = to_bq27000_device_info(psy);
148  
149 -       if (!(di->hdq_initialized)())
150 +       if (!(di->pdata->hdq_initialized)())
151                 return -EINVAL;
152  
153         switch (psp) {
154         case POWER_SUPPLY_PROP_STATUS:
155                 val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
156 +
157 +               if (!di->pdata->get_charger_online_status)
158 +                       goto use_bat;
159 +               if ((di->pdata->get_charger_online_status)()) {
160 +                       /*
161 +                        * charger is definitively present
162 +                        * we report our state in terms of what it says it
163 +                        * is doing
164 +                        */
165 +                       if (!di->pdata->get_charger_active_status)
166 +                               goto use_bat;
167 +                       if ((di->pdata->get_charger_active_status)())
168 +                               val->intval = POWER_SUPPLY_STATUS_CHARGING;
169 +                       else
170 +                               val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
171 +                       break;
172 +               }
173 +use_bat:
174 +               /*
175 +                * either the charger is not connected, or the
176 +                * platform doesn't give info about charger, use battery state
177 +                * but... battery state can be out of date by 4 seconds or
178 +                * so... use the platform callbacks if possible.
179 +                */
180                 v = hdq_read16(di, BQ27000_AI_L);
181                 if (v < 0)
182                         return v;
183 @@ -189,7 +208,7 @@ static int bq27000_battery_get_property(struct power_supply *psy,
184                         break;
185                 }
186                 /* power is actually going in or out... */
187 -               v = (di->hdq_read)(BQ27000_FLAGS);
188 +               v = (di->pdata->hdq_read)(BQ27000_FLAGS);
189                 if (v < 0)
190                         return v;
191                 if (v & BQ27000_STATUS_CHGS)
192 @@ -205,7 +224,7 @@ static int bq27000_battery_get_property(struct power_supply *psy,
193                 val->intval = v * 1000;
194                 break;
195         case POWER_SUPPLY_PROP_CURRENT_NOW:
196 -               v = (di->hdq_read)(BQ27000_FLAGS);
197 +               v = (di->pdata->hdq_read)(BQ27000_FLAGS);
198                 if (v < 0)
199                         return v;
200                 if (v & BQ27000_STATUS_CHGS)
201 @@ -215,13 +234,13 @@ static int bq27000_battery_get_property(struct power_supply *psy,
202                 v = hdq_read16(di, BQ27000_AI_L);
203                 if (v < 0)
204                         return v;
205 -               val->intval = (v * n) / di->rsense_mohms;
206 +               val->intval = (v * n) / di->pdata->rsense_mohms;
207                 break;
208         case POWER_SUPPLY_PROP_CHARGE_FULL:
209                 v = hdq_read16(di, BQ27000_LMD_L);
210                 if (v < 0)
211                         return v;
212 -               val->intval = (v * 3570) / di->rsense_mohms;
213 +               val->intval = (v * 3570) / di->pdata->rsense_mohms;
214                 break;
215         case POWER_SUPPLY_PROP_TEMP:
216                 v = hdq_read16(di, BQ27000_TEMP_L);
217 @@ -235,12 +254,12 @@ static int bq27000_battery_get_property(struct power_supply *psy,
218                 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
219                 break;
220         case POWER_SUPPLY_PROP_CAPACITY:
221 -               val->intval = (di->hdq_read)(BQ27000_RSOC);
222 +               val->intval = (di->pdata->hdq_read)(BQ27000_RSOC);
223                 if (val->intval < 0)
224                         return val->intval;
225                 break;
226         case POWER_SUPPLY_PROP_PRESENT:
227 -               v = (di->hdq_read)(BQ27000_RSOC);
228 +               v = (di->pdata->hdq_read)(BQ27000_RSOC);
229                 val->intval = !(v < 0);
230                 break;
231         case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
232 @@ -255,6 +274,12 @@ static int bq27000_battery_get_property(struct power_supply *psy,
233                         return v;
234                 val->intval = 60 * v;
235                 break;
236 +       case POWER_SUPPLY_PROP_ONLINE:
237 +               if (di->pdata->get_charger_online_status)
238 +                       val->intval = (di->pdata->get_charger_online_status)();
239 +               else
240 +                       return -EINVAL;
241 +               break;
242         default:
243                 return -EINVAL;
244         }
245 @@ -272,7 +297,8 @@ static enum power_supply_property bq27000_battery_props[] = {
246         POWER_SUPPLY_PROP_PRESENT,
247         POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
248         POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
249 -       POWER_SUPPLY_PROP_CAPACITY
250 +       POWER_SUPPLY_PROP_CAPACITY,
251 +       POWER_SUPPLY_PROP_ONLINE
252  };
253  
254  static int bq27000_battery_probe(struct platform_device *pdev)
255 @@ -301,10 +327,8 @@ static int bq27000_battery_probe(struct platform_device *pdev)
256         di->bat.get_property   = bq27000_battery_get_property;
257         di->bat.external_power_changed =
258                                   bq27000_battery_external_power_changed;
259 -       di->hdq_read = pdata->hdq_read;
260 -       di->hdq_write = pdata->hdq_write;
261 -       di->rsense_mohms = pdata->rsense_mohms;
262 -       di->hdq_initialized = pdata->hdq_initialized;
263 +       di->bat.use_for_apm = 1;
264 +       di->pdata = pdata;
265  
266         retval = power_supply_register(&pdev->dev, &di->bat);
267         if (retval) {
268 diff --git a/include/linux/bq27000_battery.h b/include/linux/bq27000_battery.h
269 index fed4287..a617466 100644
270 --- a/include/linux/bq27000_battery.h
271 +++ b/include/linux/bq27000_battery.h
272 @@ -9,6 +9,8 @@ struct bq27000_platform_data {
273         int (*hdq_read)(int);
274         int (*hdq_write)(int, u8);
275         int (*hdq_initialized)(void);
276 +       int (*get_charger_online_status)(void);
277 +       int (*get_charger_active_status)(void);
278  };
279  
280  #endif
281 -- 
282 1.5.6.3
283