aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /drivers/power
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/power')
-rw-r--r--drivers/power/Kconfig25
-rw-r--r--drivers/power/Makefile3
-rw-r--r--drivers/power/bq27x00_battery.c178
-rw-r--r--drivers/power/collie_battery.c418
-rw-r--r--drivers/power/da9030_battery.c3
-rw-r--r--drivers/power/ds2760_battery.c1
-rw-r--r--drivers/power/ds2782_battery.c1
-rw-r--r--drivers/power/max17040_battery.c1
-rw-r--r--drivers/power/max8925_power.c535
-rw-r--r--drivers/power/pcf50633-charger.c232
-rw-r--r--drivers/power/pmu_battery.c3
-rw-r--r--drivers/power/power_supply_leds.c1
-rw-r--r--drivers/power/power_supply_sysfs.c7
-rw-r--r--drivers/power/wm831x_backup.c234
-rw-r--r--drivers/power/wm831x_power.c145
-rw-r--r--drivers/power/wm8350_power.c89
-rw-r--r--drivers/power/wm97xx_battery.c17
17 files changed, 1570 insertions, 323 deletions
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index cea6cef27e89..faaa9b4d0d07 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -29,6 +29,20 @@ config APM_POWER
29 Say Y here to enable support APM status emulation using 29 Say Y here to enable support APM status emulation using
30 battery class devices. 30 battery class devices.
31 31
32config MAX8925_POWER
33 tristate "MAX8925 battery charger support"
34 depends on MFD_MAX8925
35 help
36 Say Y here to enable support for the battery charger in the Maxim
37 MAX8925 PMIC.
38
39config WM831X_BACKUP
40 tristate "WM831X backup battery charger support"
41 depends on MFD_WM831X
42 help
43 Say Y here to enable support for the backup battery charger
44 in the Wolfson Microelectronics WM831x PMICs.
45
32config WM831X_POWER 46config WM831X_POWER
33 tristate "WM831X PMU support" 47 tristate "WM831X PMU support"
34 depends on MFD_WM831X 48 depends on MFD_WM831X
@@ -77,6 +91,13 @@ config BATTERY_TOSA
77 Say Y to enable support for the battery on the Sharp Zaurus 91 Say Y to enable support for the battery on the Sharp Zaurus
78 SL-6000 (tosa) models. 92 SL-6000 (tosa) models.
79 93
94config BATTERY_COLLIE
95 tristate "Sharp SL-5500 (collie) battery"
96 depends on SA1100_COLLIE && MCP_UCB1200
97 help
98 Say Y to enable support for the battery on the Sharp Zaurus
99 SL-5500 (collie) models.
100
80config BATTERY_WM97XX 101config BATTERY_WM97XX
81 bool "WM97xx generic battery driver" 102 bool "WM97xx generic battery driver"
82 depends on TOUCHSCREEN_WM97XX=y 103 depends on TOUCHSCREEN_WM97XX=y
@@ -84,10 +105,10 @@ config BATTERY_WM97XX
84 Say Y to enable support for battery measured by WM97xx aux port. 105 Say Y to enable support for battery measured by WM97xx aux port.
85 106
86config BATTERY_BQ27x00 107config BATTERY_BQ27x00
87 tristate "BQ27200 battery driver" 108 tristate "BQ27x00 battery driver"
88 depends on I2C 109 depends on I2C
89 help 110 help
90 Say Y here to enable support for batteries with BQ27200(I2C) chip. 111 Say Y here to enable support for batteries with BQ27x00 (I2C) chips.
91 112
92config BATTERY_DA9030 113config BATTERY_DA9030
93 tristate "DA9030 battery driver" 114 tristate "DA9030 battery driver"
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index b96f29d91c28..a2ba7c85c97a 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -16,6 +16,8 @@ obj-$(CONFIG_POWER_SUPPLY) += power_supply.o
16 16
17obj-$(CONFIG_PDA_POWER) += pda_power.o 17obj-$(CONFIG_PDA_POWER) += pda_power.o
18obj-$(CONFIG_APM_POWER) += apm_power.o 18obj-$(CONFIG_APM_POWER) += apm_power.o
19obj-$(CONFIG_MAX8925_POWER) += max8925_power.o
20obj-$(CONFIG_WM831X_BACKUP) += wm831x_backup.o
19obj-$(CONFIG_WM831X_POWER) += wm831x_power.o 21obj-$(CONFIG_WM831X_POWER) += wm831x_power.o
20obj-$(CONFIG_WM8350_POWER) += wm8350_power.o 22obj-$(CONFIG_WM8350_POWER) += wm8350_power.o
21 23
@@ -24,6 +26,7 @@ obj-$(CONFIG_BATTERY_DS2782) += ds2782_battery.o
24obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o 26obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o
25obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o 27obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o
26obj-$(CONFIG_BATTERY_TOSA) += tosa_battery.o 28obj-$(CONFIG_BATTERY_TOSA) += tosa_battery.o
29obj-$(CONFIG_BATTERY_COLLIE) += collie_battery.o
27obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o 30obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o
28obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o 31obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o
29obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o 32obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c
index 62bb98124e26..3ec9c6a8896b 100644
--- a/drivers/power/bq27x00_battery.c
+++ b/drivers/power/bq27x00_battery.c
@@ -24,15 +24,25 @@
24#include <linux/power_supply.h> 24#include <linux/power_supply.h>
25#include <linux/idr.h> 25#include <linux/idr.h>
26#include <linux/i2c.h> 26#include <linux/i2c.h>
27#include <linux/slab.h>
27#include <asm/unaligned.h> 28#include <asm/unaligned.h>
28 29
29#define DRIVER_VERSION "1.0.0" 30#define DRIVER_VERSION "1.1.0"
30 31
31#define BQ27x00_REG_TEMP 0x06 32#define BQ27x00_REG_TEMP 0x06
32#define BQ27x00_REG_VOLT 0x08 33#define BQ27x00_REG_VOLT 0x08
33#define BQ27x00_REG_RSOC 0x0B /* Relative State-of-Charge */
34#define BQ27x00_REG_AI 0x14 34#define BQ27x00_REG_AI 0x14
35#define BQ27x00_REG_FLAGS 0x0A 35#define BQ27x00_REG_FLAGS 0x0A
36#define BQ27x00_REG_TTE 0x16
37#define BQ27x00_REG_TTF 0x18
38#define BQ27x00_REG_TTECP 0x26
39
40#define BQ27000_REG_RSOC 0x0B /* Relative State-of-Charge */
41#define BQ27000_FLAG_CHGS BIT(7)
42
43#define BQ27500_REG_SOC 0x2c
44#define BQ27500_FLAG_DSC BIT(0)
45#define BQ27500_FLAG_FC BIT(9)
36 46
37/* If the system has several batteries we need a different name for each 47/* If the system has several batteries we need a different name for each
38 * of them... 48 * of them...
@@ -46,25 +56,28 @@ struct bq27x00_access_methods {
46 struct bq27x00_device_info *di); 56 struct bq27x00_device_info *di);
47}; 57};
48 58
59enum bq27x00_chip { BQ27000, BQ27500 };
60
49struct bq27x00_device_info { 61struct bq27x00_device_info {
50 struct device *dev; 62 struct device *dev;
51 int id; 63 int id;
52 int voltage_uV;
53 int current_uA;
54 int temp_C;
55 int charge_rsoc;
56 struct bq27x00_access_methods *bus; 64 struct bq27x00_access_methods *bus;
57 struct power_supply bat; 65 struct power_supply bat;
66 enum bq27x00_chip chip;
58 67
59 struct i2c_client *client; 68 struct i2c_client *client;
60}; 69};
61 70
62static enum power_supply_property bq27x00_battery_props[] = { 71static enum power_supply_property bq27x00_battery_props[] = {
72 POWER_SUPPLY_PROP_STATUS,
63 POWER_SUPPLY_PROP_PRESENT, 73 POWER_SUPPLY_PROP_PRESENT,
64 POWER_SUPPLY_PROP_VOLTAGE_NOW, 74 POWER_SUPPLY_PROP_VOLTAGE_NOW,
65 POWER_SUPPLY_PROP_CURRENT_NOW, 75 POWER_SUPPLY_PROP_CURRENT_NOW,
66 POWER_SUPPLY_PROP_CAPACITY, 76 POWER_SUPPLY_PROP_CAPACITY,
67 POWER_SUPPLY_PROP_TEMP, 77 POWER_SUPPLY_PROP_TEMP,
78 POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
79 POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
80 POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
68}; 81};
69 82
70/* 83/*
@@ -74,16 +87,11 @@ static enum power_supply_property bq27x00_battery_props[] = {
74static int bq27x00_read(u8 reg, int *rt_value, int b_single, 87static int bq27x00_read(u8 reg, int *rt_value, int b_single,
75 struct bq27x00_device_info *di) 88 struct bq27x00_device_info *di)
76{ 89{
77 int ret; 90 return di->bus->read(reg, rt_value, b_single, di);
78
79 ret = di->bus->read(reg, rt_value, b_single, di);
80 *rt_value = be16_to_cpu(*rt_value);
81
82 return ret;
83} 91}
84 92
85/* 93/*
86 * Return the battery temperature in Celsius degrees 94 * Return the battery temperature in tenths of degree Celsius
87 * Or < 0 if something fails. 95 * Or < 0 if something fails.
88 */ 96 */
89static int bq27x00_battery_temperature(struct bq27x00_device_info *di) 97static int bq27x00_battery_temperature(struct bq27x00_device_info *di)
@@ -97,7 +105,10 @@ static int bq27x00_battery_temperature(struct bq27x00_device_info *di)
97 return ret; 105 return ret;
98 } 106 }
99 107
100 return (temp >> 2) - 273; 108 if (di->chip == BQ27500)
109 return temp - 2731;
110 else
111 return ((temp >> 2) - 273) * 10;
101} 112}
102 113
103/* 114/*
@@ -115,7 +126,7 @@ static int bq27x00_battery_voltage(struct bq27x00_device_info *di)
115 return ret; 126 return ret;
116 } 127 }
117 128
118 return volt; 129 return volt * 1000;
119} 130}
120 131
121/* 132/*
@@ -134,16 +145,23 @@ static int bq27x00_battery_current(struct bq27x00_device_info *di)
134 dev_err(di->dev, "error reading current\n"); 145 dev_err(di->dev, "error reading current\n");
135 return 0; 146 return 0;
136 } 147 }
137 ret = bq27x00_read(BQ27x00_REG_FLAGS, &flags, 0, di); 148
138 if (ret < 0) { 149 if (di->chip == BQ27500) {
139 dev_err(di->dev, "error reading flags\n"); 150 /* bq27500 returns signed value */
140 return 0; 151 curr = (int)(s16)curr;
141 } 152 } else {
142 if ((flags & (1 << 7)) != 0) { 153 ret = bq27x00_read(BQ27x00_REG_FLAGS, &flags, 0, di);
143 dev_dbg(di->dev, "negative current!\n"); 154 if (ret < 0) {
144 return -curr; 155 dev_err(di->dev, "error reading flags\n");
156 return 0;
157 }
158 if (flags & BQ27000_FLAG_CHGS) {
159 dev_dbg(di->dev, "negative current!\n");
160 curr = -curr;
161 }
145 } 162 }
146 return curr; 163
164 return curr * 1000;
147} 165}
148 166
149/* 167/*
@@ -155,13 +173,70 @@ static int bq27x00_battery_rsoc(struct bq27x00_device_info *di)
155 int ret; 173 int ret;
156 int rsoc = 0; 174 int rsoc = 0;
157 175
158 ret = bq27x00_read(BQ27x00_REG_RSOC, &rsoc, 1, di); 176 if (di->chip == BQ27500)
177 ret = bq27x00_read(BQ27500_REG_SOC, &rsoc, 0, di);
178 else
179 ret = bq27x00_read(BQ27000_REG_RSOC, &rsoc, 1, di);
159 if (ret) { 180 if (ret) {
160 dev_err(di->dev, "error reading relative State-of-Charge\n"); 181 dev_err(di->dev, "error reading relative State-of-Charge\n");
161 return ret; 182 return ret;
162 } 183 }
163 184
164 return rsoc >> 8; 185 return rsoc;
186}
187
188static int bq27x00_battery_status(struct bq27x00_device_info *di,
189 union power_supply_propval *val)
190{
191 int flags = 0;
192 int status;
193 int ret;
194
195 ret = bq27x00_read(BQ27x00_REG_FLAGS, &flags, 0, di);
196 if (ret < 0) {
197 dev_err(di->dev, "error reading flags\n");
198 return ret;
199 }
200
201 if (di->chip == BQ27500) {
202 if (flags & BQ27500_FLAG_FC)
203 status = POWER_SUPPLY_STATUS_FULL;
204 else if (flags & BQ27500_FLAG_DSC)
205 status = POWER_SUPPLY_STATUS_DISCHARGING;
206 else
207 status = POWER_SUPPLY_STATUS_CHARGING;
208 } else {
209 if (flags & BQ27000_FLAG_CHGS)
210 status = POWER_SUPPLY_STATUS_CHARGING;
211 else
212 status = POWER_SUPPLY_STATUS_DISCHARGING;
213 }
214
215 val->intval = status;
216 return 0;
217}
218
219/*
220 * Read a time register.
221 * Return < 0 if something fails.
222 */
223static int bq27x00_battery_time(struct bq27x00_device_info *di, int reg,
224 union power_supply_propval *val)
225{
226 int tval = 0;
227 int ret;
228
229 ret = bq27x00_read(reg, &tval, 0, di);
230 if (ret) {
231 dev_err(di->dev, "error reading register %02x\n", reg);
232 return ret;
233 }
234
235 if (tval == 65535)
236 return -ENODATA;
237
238 val->intval = tval * 60;
239 return 0;
165} 240}
166 241
167#define to_bq27x00_device_info(x) container_of((x), \ 242#define to_bq27x00_device_info(x) container_of((x), \
@@ -171,9 +246,13 @@ static int bq27x00_battery_get_property(struct power_supply *psy,
171 enum power_supply_property psp, 246 enum power_supply_property psp,
172 union power_supply_propval *val) 247 union power_supply_propval *val)
173{ 248{
249 int ret = 0;
174 struct bq27x00_device_info *di = to_bq27x00_device_info(psy); 250 struct bq27x00_device_info *di = to_bq27x00_device_info(psy);
175 251
176 switch (psp) { 252 switch (psp) {
253 case POWER_SUPPLY_PROP_STATUS:
254 ret = bq27x00_battery_status(di, val);
255 break;
177 case POWER_SUPPLY_PROP_VOLTAGE_NOW: 256 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
178 case POWER_SUPPLY_PROP_PRESENT: 257 case POWER_SUPPLY_PROP_PRESENT:
179 val->intval = bq27x00_battery_voltage(di); 258 val->intval = bq27x00_battery_voltage(di);
@@ -189,11 +268,20 @@ static int bq27x00_battery_get_property(struct power_supply *psy,
189 case POWER_SUPPLY_PROP_TEMP: 268 case POWER_SUPPLY_PROP_TEMP:
190 val->intval = bq27x00_battery_temperature(di); 269 val->intval = bq27x00_battery_temperature(di);
191 break; 270 break;
271 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
272 ret = bq27x00_battery_time(di, BQ27x00_REG_TTE, val);
273 break;
274 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
275 ret = bq27x00_battery_time(di, BQ27x00_REG_TTECP, val);
276 break;
277 case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:
278 ret = bq27x00_battery_time(di, BQ27x00_REG_TTF, val);
279 break;
192 default: 280 default:
193 return -EINVAL; 281 return -EINVAL;
194 } 282 }
195 283
196 return 0; 284 return ret;
197} 285}
198 286
199static void bq27x00_powersupply_init(struct bq27x00_device_info *di) 287static void bq27x00_powersupply_init(struct bq27x00_device_info *di)
@@ -206,10 +294,10 @@ static void bq27x00_powersupply_init(struct bq27x00_device_info *di)
206} 294}
207 295
208/* 296/*
209 * BQ27200 specific code 297 * i2c specific code
210 */ 298 */
211 299
212static int bq27200_read(u8 reg, int *rt_value, int b_single, 300static int bq27x00_read_i2c(u8 reg, int *rt_value, int b_single,
213 struct bq27x00_device_info *di) 301 struct bq27x00_device_info *di)
214{ 302{
215 struct i2c_client *client = di->client; 303 struct i2c_client *client = di->client;
@@ -238,7 +326,7 @@ static int bq27200_read(u8 reg, int *rt_value, int b_single,
238 err = i2c_transfer(client->adapter, msg, 1); 326 err = i2c_transfer(client->adapter, msg, 1);
239 if (err >= 0) { 327 if (err >= 0) {
240 if (!b_single) 328 if (!b_single)
241 *rt_value = get_unaligned_be16(data); 329 *rt_value = get_unaligned_le16(data);
242 else 330 else
243 *rt_value = data[0]; 331 *rt_value = data[0];
244 332
@@ -248,7 +336,7 @@ static int bq27200_read(u8 reg, int *rt_value, int b_single,
248 return err; 336 return err;
249} 337}
250 338
251static int bq27200_battery_probe(struct i2c_client *client, 339static int bq27x00_battery_probe(struct i2c_client *client,
252 const struct i2c_device_id *id) 340 const struct i2c_device_id *id)
253{ 341{
254 char *name; 342 char *name;
@@ -267,7 +355,7 @@ static int bq27200_battery_probe(struct i2c_client *client,
267 if (retval < 0) 355 if (retval < 0)
268 return retval; 356 return retval;
269 357
270 name = kasprintf(GFP_KERNEL, "bq27200-%d", num); 358 name = kasprintf(GFP_KERNEL, "%s-%d", id->name, num);
271 if (!name) { 359 if (!name) {
272 dev_err(&client->dev, "failed to allocate device name\n"); 360 dev_err(&client->dev, "failed to allocate device name\n");
273 retval = -ENOMEM; 361 retval = -ENOMEM;
@@ -281,6 +369,7 @@ static int bq27200_battery_probe(struct i2c_client *client,
281 goto batt_failed_2; 369 goto batt_failed_2;
282 } 370 }
283 di->id = num; 371 di->id = num;
372 di->chip = id->driver_data;
284 373
285 bus = kzalloc(sizeof(*bus), GFP_KERNEL); 374 bus = kzalloc(sizeof(*bus), GFP_KERNEL);
286 if (!bus) { 375 if (!bus) {
@@ -293,7 +382,7 @@ static int bq27200_battery_probe(struct i2c_client *client,
293 i2c_set_clientdata(client, di); 382 i2c_set_clientdata(client, di);
294 di->dev = &client->dev; 383 di->dev = &client->dev;
295 di->bat.name = name; 384 di->bat.name = name;
296 bus->read = &bq27200_read; 385 bus->read = &bq27x00_read_i2c;
297 di->bus = bus; 386 di->bus = bus;
298 di->client = client; 387 di->client = client;
299 388
@@ -323,7 +412,7 @@ batt_failed_1:
323 return retval; 412 return retval;
324} 413}
325 414
326static int bq27200_battery_remove(struct i2c_client *client) 415static int bq27x00_battery_remove(struct i2c_client *client)
327{ 416{
328 struct bq27x00_device_info *di = i2c_get_clientdata(client); 417 struct bq27x00_device_info *di = i2c_get_clientdata(client);
329 418
@@ -344,27 +433,28 @@ static int bq27200_battery_remove(struct i2c_client *client)
344 * Module stuff 433 * Module stuff
345 */ 434 */
346 435
347static const struct i2c_device_id bq27200_id[] = { 436static const struct i2c_device_id bq27x00_id[] = {
348 { "bq27200", 0 }, 437 { "bq27200", BQ27000 }, /* bq27200 is same as bq27000, but with i2c */
438 { "bq27500", BQ27500 },
349 {}, 439 {},
350}; 440};
351 441
352static struct i2c_driver bq27200_battery_driver = { 442static struct i2c_driver bq27x00_battery_driver = {
353 .driver = { 443 .driver = {
354 .name = "bq27200-battery", 444 .name = "bq27x00-battery",
355 }, 445 },
356 .probe = bq27200_battery_probe, 446 .probe = bq27x00_battery_probe,
357 .remove = bq27200_battery_remove, 447 .remove = bq27x00_battery_remove,
358 .id_table = bq27200_id, 448 .id_table = bq27x00_id,
359}; 449};
360 450
361static int __init bq27x00_battery_init(void) 451static int __init bq27x00_battery_init(void)
362{ 452{
363 int ret; 453 int ret;
364 454
365 ret = i2c_add_driver(&bq27200_battery_driver); 455 ret = i2c_add_driver(&bq27x00_battery_driver);
366 if (ret) 456 if (ret)
367 printk(KERN_ERR "Unable to register BQ27200 driver\n"); 457 printk(KERN_ERR "Unable to register BQ27x00 driver\n");
368 458
369 return ret; 459 return ret;
370} 460}
@@ -372,7 +462,7 @@ module_init(bq27x00_battery_init);
372 462
373static void __exit bq27x00_battery_exit(void) 463static void __exit bq27x00_battery_exit(void)
374{ 464{
375 i2c_del_driver(&bq27200_battery_driver); 465 i2c_del_driver(&bq27x00_battery_driver);
376} 466}
377module_exit(bq27x00_battery_exit); 467module_exit(bq27x00_battery_exit);
378 468
diff --git a/drivers/power/collie_battery.c b/drivers/power/collie_battery.c
new file mode 100644
index 000000000000..039f41ae217d
--- /dev/null
+++ b/drivers/power/collie_battery.c
@@ -0,0 +1,418 @@
1/*
2 * Battery and Power Management code for the Sharp SL-5x00
3 *
4 * Copyright (C) 2009 Thomas Kunze
5 *
6 * based on tosa_battery.c
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 */
13#include <linux/kernel.h>
14#include <linux/module.h>
15#include <linux/power_supply.h>
16#include <linux/delay.h>
17#include <linux/spinlock.h>
18#include <linux/interrupt.h>
19#include <linux/gpio.h>
20#include <linux/mfd/ucb1x00.h>
21
22#include <asm/mach/sharpsl_param.h>
23#include <asm/mach-types.h>
24#include <mach/collie.h>
25
26static DEFINE_MUTEX(bat_lock); /* protects gpio pins */
27static struct work_struct bat_work;
28static struct ucb1x00 *ucb;
29
30struct collie_bat {
31 int status;
32 struct power_supply psy;
33 int full_chrg;
34
35 struct mutex work_lock; /* protects data */
36
37 bool (*is_present)(struct collie_bat *bat);
38 int gpio_full;
39 int gpio_charge_on;
40
41 int technology;
42
43 int gpio_bat;
44 int adc_bat;
45 int adc_bat_divider;
46 int bat_max;
47 int bat_min;
48
49 int gpio_temp;
50 int adc_temp;
51 int adc_temp_divider;
52};
53
54static struct collie_bat collie_bat_main;
55
56static unsigned long collie_read_bat(struct collie_bat *bat)
57{
58 unsigned long value = 0;
59
60 if (bat->gpio_bat < 0 || bat->adc_bat < 0)
61 return 0;
62 mutex_lock(&bat_lock);
63 gpio_set_value(bat->gpio_bat, 1);
64 msleep(5);
65 ucb1x00_adc_enable(ucb);
66 value = ucb1x00_adc_read(ucb, bat->adc_bat, UCB_SYNC);
67 ucb1x00_adc_disable(ucb);
68 gpio_set_value(bat->gpio_bat, 0);
69 mutex_unlock(&bat_lock);
70 value = value * 1000000 / bat->adc_bat_divider;
71
72 return value;
73}
74
75static unsigned long collie_read_temp(struct collie_bat *bat)
76{
77 unsigned long value = 0;
78 if (bat->gpio_temp < 0 || bat->adc_temp < 0)
79 return 0;
80
81 mutex_lock(&bat_lock);
82 gpio_set_value(bat->gpio_temp, 1);
83 msleep(5);
84 ucb1x00_adc_enable(ucb);
85 value = ucb1x00_adc_read(ucb, bat->adc_temp, UCB_SYNC);
86 ucb1x00_adc_disable(ucb);
87 gpio_set_value(bat->gpio_temp, 0);
88 mutex_unlock(&bat_lock);
89
90 value = value * 10000 / bat->adc_temp_divider;
91
92 return value;
93}
94
95static int collie_bat_get_property(struct power_supply *psy,
96 enum power_supply_property psp,
97 union power_supply_propval *val)
98{
99 int ret = 0;
100 struct collie_bat *bat = container_of(psy, struct collie_bat, psy);
101
102 if (bat->is_present && !bat->is_present(bat)
103 && psp != POWER_SUPPLY_PROP_PRESENT) {
104 return -ENODEV;
105 }
106
107 switch (psp) {
108 case POWER_SUPPLY_PROP_STATUS:
109 val->intval = bat->status;
110 break;
111 case POWER_SUPPLY_PROP_TECHNOLOGY:
112 val->intval = bat->technology;
113 break;
114 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
115 val->intval = collie_read_bat(bat);
116 break;
117 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
118 if (bat->full_chrg == -1)
119 val->intval = bat->bat_max;
120 else
121 val->intval = bat->full_chrg;
122 break;
123 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
124 val->intval = bat->bat_max;
125 break;
126 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
127 val->intval = bat->bat_min;
128 break;
129 case POWER_SUPPLY_PROP_TEMP:
130 val->intval = collie_read_temp(bat);
131 break;
132 case POWER_SUPPLY_PROP_PRESENT:
133 val->intval = bat->is_present ? bat->is_present(bat) : 1;
134 break;
135 default:
136 ret = -EINVAL;
137 break;
138 }
139 return ret;
140}
141
142static void collie_bat_external_power_changed(struct power_supply *psy)
143{
144 schedule_work(&bat_work);
145}
146
147static irqreturn_t collie_bat_gpio_isr(int irq, void *data)
148{
149 pr_info("collie_bat_gpio irq: %d\n", gpio_get_value(irq_to_gpio(irq)));
150 schedule_work(&bat_work);
151 return IRQ_HANDLED;
152}
153
154static void collie_bat_update(struct collie_bat *bat)
155{
156 int old;
157 struct power_supply *psy = &bat->psy;
158
159 mutex_lock(&bat->work_lock);
160
161 old = bat->status;
162
163 if (bat->is_present && !bat->is_present(bat)) {
164 printk(KERN_NOTICE "%s not present\n", psy->name);
165 bat->status = POWER_SUPPLY_STATUS_UNKNOWN;
166 bat->full_chrg = -1;
167 } else if (power_supply_am_i_supplied(psy)) {
168 if (bat->status == POWER_SUPPLY_STATUS_DISCHARGING) {
169 gpio_set_value(bat->gpio_charge_on, 1);
170 mdelay(15);
171 }
172
173 if (gpio_get_value(bat->gpio_full)) {
174 if (old == POWER_SUPPLY_STATUS_CHARGING ||
175 bat->full_chrg == -1)
176 bat->full_chrg = collie_read_bat(bat);
177
178 gpio_set_value(bat->gpio_charge_on, 0);
179 bat->status = POWER_SUPPLY_STATUS_FULL;
180 } else {
181 gpio_set_value(bat->gpio_charge_on, 1);
182 bat->status = POWER_SUPPLY_STATUS_CHARGING;
183 }
184 } else {
185 gpio_set_value(bat->gpio_charge_on, 0);
186 bat->status = POWER_SUPPLY_STATUS_DISCHARGING;
187 }
188
189 if (old != bat->status)
190 power_supply_changed(psy);
191
192 mutex_unlock(&bat->work_lock);
193}
194
195static void collie_bat_work(struct work_struct *work)
196{
197 collie_bat_update(&collie_bat_main);
198}
199
200
201static enum power_supply_property collie_bat_main_props[] = {
202 POWER_SUPPLY_PROP_STATUS,
203 POWER_SUPPLY_PROP_TECHNOLOGY,
204 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
205 POWER_SUPPLY_PROP_VOLTAGE_NOW,
206 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
207 POWER_SUPPLY_PROP_VOLTAGE_MAX,
208 POWER_SUPPLY_PROP_PRESENT,
209 POWER_SUPPLY_PROP_TEMP,
210};
211
212static enum power_supply_property collie_bat_bu_props[] = {
213 POWER_SUPPLY_PROP_STATUS,
214 POWER_SUPPLY_PROP_TECHNOLOGY,
215 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
216 POWER_SUPPLY_PROP_VOLTAGE_NOW,
217 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
218 POWER_SUPPLY_PROP_VOLTAGE_MAX,
219 POWER_SUPPLY_PROP_PRESENT,
220};
221
222static struct collie_bat collie_bat_main = {
223 .status = POWER_SUPPLY_STATUS_DISCHARGING,
224 .full_chrg = -1,
225 .psy = {
226 .name = "main-battery",
227 .type = POWER_SUPPLY_TYPE_BATTERY,
228 .properties = collie_bat_main_props,
229 .num_properties = ARRAY_SIZE(collie_bat_main_props),
230 .get_property = collie_bat_get_property,
231 .external_power_changed = collie_bat_external_power_changed,
232 .use_for_apm = 1,
233 },
234
235 .gpio_full = COLLIE_GPIO_CO,
236 .gpio_charge_on = COLLIE_GPIO_CHARGE_ON,
237
238 .technology = POWER_SUPPLY_TECHNOLOGY_LIPO,
239
240 .gpio_bat = COLLIE_GPIO_MBAT_ON,
241 .adc_bat = UCB_ADC_INP_AD1,
242 .adc_bat_divider = 155,
243 .bat_max = 4310000,
244 .bat_min = 1551 * 1000000 / 414,
245
246 .gpio_temp = COLLIE_GPIO_TMP_ON,
247 .adc_temp = UCB_ADC_INP_AD0,
248 .adc_temp_divider = 10000,
249};
250
251static struct collie_bat collie_bat_bu = {
252 .status = POWER_SUPPLY_STATUS_UNKNOWN,
253 .full_chrg = -1,
254
255 .psy = {
256 .name = "backup-battery",
257 .type = POWER_SUPPLY_TYPE_BATTERY,
258 .properties = collie_bat_bu_props,
259 .num_properties = ARRAY_SIZE(collie_bat_bu_props),
260 .get_property = collie_bat_get_property,
261 .external_power_changed = collie_bat_external_power_changed,
262 },
263
264 .gpio_full = -1,
265 .gpio_charge_on = -1,
266
267 .technology = POWER_SUPPLY_TECHNOLOGY_LiMn,
268
269 .gpio_bat = COLLIE_GPIO_BBAT_ON,
270 .adc_bat = UCB_ADC_INP_AD1,
271 .adc_bat_divider = 155,
272 .bat_max = 3000000,
273 .bat_min = 1900000,
274
275 .gpio_temp = -1,
276 .adc_temp = -1,
277 .adc_temp_divider = -1,
278};
279
280static struct {
281 int gpio;
282 char *name;
283 bool output;
284 int value;
285} gpios[] = {
286 { COLLIE_GPIO_CO, "main battery full", 0, 0 },
287 { COLLIE_GPIO_MAIN_BAT_LOW, "main battery low", 0, 0 },
288 { COLLIE_GPIO_CHARGE_ON, "main charge on", 1, 0 },
289 { COLLIE_GPIO_MBAT_ON, "main battery", 1, 0 },
290 { COLLIE_GPIO_TMP_ON, "main battery temp", 1, 0 },
291 { COLLIE_GPIO_BBAT_ON, "backup battery", 1, 0 },
292};
293
294#ifdef CONFIG_PM
295static int collie_bat_suspend(struct ucb1x00_dev *dev, pm_message_t state)
296{
297 /* flush all pending status updates */
298 flush_scheduled_work();
299 return 0;
300}
301
302static int collie_bat_resume(struct ucb1x00_dev *dev)
303{
304 /* things may have changed while we were away */
305 schedule_work(&bat_work);
306 return 0;
307}
308#else
309#define collie_bat_suspend NULL
310#define collie_bat_resume NULL
311#endif
312
313static int __devinit collie_bat_probe(struct ucb1x00_dev *dev)
314{
315 int ret;
316 int i;
317
318 if (!machine_is_collie())
319 return -ENODEV;
320
321 ucb = dev->ucb;
322
323 for (i = 0; i < ARRAY_SIZE(gpios); i++) {
324 ret = gpio_request(gpios[i].gpio, gpios[i].name);
325 if (ret) {
326 i--;
327 goto err_gpio;
328 }
329
330 if (gpios[i].output)
331 ret = gpio_direction_output(gpios[i].gpio,
332 gpios[i].value);
333 else
334 ret = gpio_direction_input(gpios[i].gpio);
335
336 if (ret)
337 goto err_gpio;
338 }
339
340 mutex_init(&collie_bat_main.work_lock);
341
342 INIT_WORK(&bat_work, collie_bat_work);
343
344 ret = power_supply_register(&dev->ucb->dev, &collie_bat_main.psy);
345 if (ret)
346 goto err_psy_reg_main;
347 ret = power_supply_register(&dev->ucb->dev, &collie_bat_bu.psy);
348 if (ret)
349 goto err_psy_reg_bu;
350
351 ret = request_irq(gpio_to_irq(COLLIE_GPIO_CO),
352 collie_bat_gpio_isr,
353 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
354 "main full", &collie_bat_main);
355 if (!ret) {
356 schedule_work(&bat_work);
357 return 0;
358 }
359 power_supply_unregister(&collie_bat_bu.psy);
360err_psy_reg_bu:
361 power_supply_unregister(&collie_bat_main.psy);
362err_psy_reg_main:
363
364 /* see comment in collie_bat_remove */
365 flush_scheduled_work();
366
367 i--;
368err_gpio:
369 for (; i >= 0; i--)
370 gpio_free(gpios[i].gpio);
371
372 return ret;
373}
374
375static void __devexit collie_bat_remove(struct ucb1x00_dev *dev)
376{
377 int i;
378
379 free_irq(gpio_to_irq(COLLIE_GPIO_CO), &collie_bat_main);
380
381 power_supply_unregister(&collie_bat_bu.psy);
382 power_supply_unregister(&collie_bat_main.psy);
383
384 /*
385 * now flush all pending work.
386 * we won't get any more schedules, since all
387 * sources (isr and external_power_changed)
388 * are unregistered now.
389 */
390 flush_scheduled_work();
391
392 for (i = ARRAY_SIZE(gpios) - 1; i >= 0; i--)
393 gpio_free(gpios[i].gpio);
394}
395
396static struct ucb1x00_driver collie_bat_driver = {
397 .add = collie_bat_probe,
398 .remove = __devexit_p(collie_bat_remove),
399 .suspend = collie_bat_suspend,
400 .resume = collie_bat_resume,
401};
402
403static int __init collie_bat_init(void)
404{
405 return ucb1x00_register_driver(&collie_bat_driver);
406}
407
408static void __exit collie_bat_exit(void)
409{
410 ucb1x00_unregister_driver(&collie_bat_driver);
411}
412
413module_init(collie_bat_init);
414module_exit(collie_bat_exit);
415
416MODULE_LICENSE("GPL");
417MODULE_AUTHOR("Thomas Kunze");
418MODULE_DESCRIPTION("Collie battery driver");
diff --git a/drivers/power/da9030_battery.c b/drivers/power/da9030_battery.c
index 3364198134a1..d2c793cf6765 100644
--- a/drivers/power/da9030_battery.c
+++ b/drivers/power/da9030_battery.c
@@ -10,6 +10,7 @@
10 */ 10 */
11 11
12#include <linux/kernel.h> 12#include <linux/kernel.h>
13#include <linux/slab.h>
13#include <linux/init.h> 14#include <linux/init.h>
14#include <linux/types.h> 15#include <linux/types.h>
15#include <linux/device.h> 16#include <linux/device.h>
@@ -509,7 +510,7 @@ static int da9030_battery_probe(struct platform_device *pdev)
509 510
510 charger->master = pdev->dev.parent; 511 charger->master = pdev->dev.parent;
511 512
512 /* 10 seconds between monotor runs unless platfrom defines other 513 /* 10 seconds between monitor runs unless platform defines other
513 interval */ 514 interval */
514 charger->interval = msecs_to_jiffies( 515 charger->interval = msecs_to_jiffies(
515 (pdata->batmon_interval ? : 10) * 1000); 516 (pdata->batmon_interval ? : 10) * 1000);
diff --git a/drivers/power/ds2760_battery.c b/drivers/power/ds2760_battery.c
index 6f1dba5a519d..3bf8d1f622e3 100644
--- a/drivers/power/ds2760_battery.c
+++ b/drivers/power/ds2760_battery.c
@@ -24,6 +24,7 @@
24#include <linux/jiffies.h> 24#include <linux/jiffies.h>
25#include <linux/workqueue.h> 25#include <linux/workqueue.h>
26#include <linux/pm.h> 26#include <linux/pm.h>
27#include <linux/slab.h>
27#include <linux/platform_device.h> 28#include <linux/platform_device.h>
28#include <linux/power_supply.h> 29#include <linux/power_supply.h>
29 30
diff --git a/drivers/power/ds2782_battery.c b/drivers/power/ds2782_battery.c
index da14f374cb60..99c89976a902 100644
--- a/drivers/power/ds2782_battery.c
+++ b/drivers/power/ds2782_battery.c
@@ -19,6 +19,7 @@
19#include <linux/i2c.h> 19#include <linux/i2c.h>
20#include <linux/idr.h> 20#include <linux/idr.h>
21#include <linux/power_supply.h> 21#include <linux/power_supply.h>
22#include <linux/slab.h>
22 23
23#define DS2782_REG_RARC 0x06 /* Remaining active relative capacity */ 24#define DS2782_REG_RARC 0x06 /* Remaining active relative capacity */
24 25
diff --git a/drivers/power/max17040_battery.c b/drivers/power/max17040_battery.c
index 87b98bf27ae1..f3e22c9fe20a 100644
--- a/drivers/power/max17040_battery.c
+++ b/drivers/power/max17040_battery.c
@@ -19,6 +19,7 @@
19#include <linux/delay.h> 19#include <linux/delay.h>
20#include <linux/power_supply.h> 20#include <linux/power_supply.h>
21#include <linux/max17040_battery.h> 21#include <linux/max17040_battery.h>
22#include <linux/slab.h>
22 23
23#define MAX17040_VCELL_MSB 0x02 24#define MAX17040_VCELL_MSB 0x02
24#define MAX17040_VCELL_LSB 0x03 25#define MAX17040_VCELL_LSB 0x03
diff --git a/drivers/power/max8925_power.c b/drivers/power/max8925_power.c
new file mode 100644
index 000000000000..8e5aec260866
--- /dev/null
+++ b/drivers/power/max8925_power.c
@@ -0,0 +1,535 @@
1/*
2 * Battery driver for Maxim MAX8925
3 *
4 * Copyright (c) 2009-2010 Marvell International Ltd.
5 * Haojian Zhuang <haojian.zhuang@marvell.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/module.h>
13#include <linux/err.h>
14#include <linux/slab.h>
15#include <linux/i2c.h>
16#include <linux/interrupt.h>
17#include <linux/platform_device.h>
18#include <linux/power_supply.h>
19#include <linux/mfd/max8925.h>
20
21/* registers in GPM */
22#define MAX8925_OUT5VEN 0x54
23#define MAX8925_OUT3VEN 0x58
24#define MAX8925_CHG_CNTL1 0x7c
25
26/* bits definition */
27#define MAX8925_CHG_STAT_VSYSLOW (1 << 0)
28#define MAX8925_CHG_STAT_MODE_MASK (3 << 2)
29#define MAX8925_CHG_STAT_EN_MASK (1 << 4)
30#define MAX8925_CHG_MBDET (1 << 1)
31#define MAX8925_CHG_AC_RANGE_MASK (3 << 6)
32
33/* registers in ADC */
34#define MAX8925_ADC_RES_CNFG1 0x06
35#define MAX8925_ADC_AVG_CNFG1 0x07
36#define MAX8925_ADC_ACQ_CNFG1 0x08
37#define MAX8925_ADC_ACQ_CNFG2 0x09
38/* 2 bytes registers in below. MSB is 1st, LSB is 2nd. */
39#define MAX8925_ADC_AUX2 0x62
40#define MAX8925_ADC_VCHG 0x64
41#define MAX8925_ADC_VBBATT 0x66
42#define MAX8925_ADC_VMBATT 0x68
43#define MAX8925_ADC_ISNS 0x6a
44#define MAX8925_ADC_THM 0x6c
45#define MAX8925_ADC_TDIE 0x6e
46#define MAX8925_CMD_AUX2 0xc8
47#define MAX8925_CMD_VCHG 0xd0
48#define MAX8925_CMD_VBBATT 0xd8
49#define MAX8925_CMD_VMBATT 0xe0
50#define MAX8925_CMD_ISNS 0xe8
51#define MAX8925_CMD_THM 0xf0
52#define MAX8925_CMD_TDIE 0xf8
53
54enum {
55 MEASURE_AUX2,
56 MEASURE_VCHG,
57 MEASURE_VBBATT,
58 MEASURE_VMBATT,
59 MEASURE_ISNS,
60 MEASURE_THM,
61 MEASURE_TDIE,
62 MEASURE_MAX,
63};
64
65struct max8925_power_info {
66 struct max8925_chip *chip;
67 struct i2c_client *gpm;
68 struct i2c_client *adc;
69
70 struct power_supply ac;
71 struct power_supply usb;
72 struct power_supply battery;
73 int irq_base;
74 unsigned ac_online:1;
75 unsigned usb_online:1;
76 unsigned bat_online:1;
77 unsigned chg_mode:2;
78 unsigned batt_detect:1; /* detecing MB by ID pin */
79 unsigned topoff_threshold:2;
80 unsigned fast_charge:3;
81
82 int (*set_charger) (int);
83};
84
85static int __set_charger(struct max8925_power_info *info, int enable)
86{
87 struct max8925_chip *chip = info->chip;
88 if (enable) {
89 /* enable charger in platform */
90 if (info->set_charger)
91 info->set_charger(1);
92 /* enable charger */
93 max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 1 << 7, 0);
94 } else {
95 /* disable charge */
96 max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 1 << 7, 1 << 7);
97 if (info->set_charger)
98 info->set_charger(0);
99 }
100 dev_dbg(chip->dev, "%s\n", (enable) ? "Enable charger"
101 : "Disable charger");
102 return 0;
103}
104
105static irqreturn_t max8925_charger_handler(int irq, void *data)
106{
107 struct max8925_power_info *info = (struct max8925_power_info *)data;
108 struct max8925_chip *chip = info->chip;
109
110 switch (irq - chip->irq_base) {
111 case MAX8925_IRQ_VCHG_DC_R:
112 info->ac_online = 1;
113 __set_charger(info, 1);
114 dev_dbg(chip->dev, "Adapter inserted\n");
115 break;
116 case MAX8925_IRQ_VCHG_DC_F:
117 info->ac_online = 0;
118 __set_charger(info, 0);
119 dev_dbg(chip->dev, "Adapter is removal\n");
120 break;
121 case MAX8925_IRQ_VCHG_USB_R:
122 info->usb_online = 1;
123 __set_charger(info, 1);
124 dev_dbg(chip->dev, "USB inserted\n");
125 break;
126 case MAX8925_IRQ_VCHG_USB_F:
127 info->usb_online = 0;
128 __set_charger(info, 0);
129 dev_dbg(chip->dev, "USB is removal\n");
130 break;
131 case MAX8925_IRQ_VCHG_THM_OK_F:
132 /* Battery is not ready yet */
133 dev_dbg(chip->dev, "Battery temperature is out of range\n");
134 case MAX8925_IRQ_VCHG_DC_OVP:
135 dev_dbg(chip->dev, "Error detection\n");
136 __set_charger(info, 0);
137 break;
138 case MAX8925_IRQ_VCHG_THM_OK_R:
139 /* Battery is ready now */
140 dev_dbg(chip->dev, "Battery temperature is in range\n");
141 break;
142 case MAX8925_IRQ_VCHG_SYSLOW_R:
143 /* VSYS is low */
144 dev_info(chip->dev, "Sys power is too low\n");
145 break;
146 case MAX8925_IRQ_VCHG_SYSLOW_F:
147 dev_dbg(chip->dev, "Sys power is above low threshold\n");
148 break;
149 case MAX8925_IRQ_VCHG_DONE:
150 __set_charger(info, 0);
151 dev_dbg(chip->dev, "Charging is done\n");
152 break;
153 case MAX8925_IRQ_VCHG_TOPOFF:
154 dev_dbg(chip->dev, "Charging in top-off mode\n");
155 break;
156 case MAX8925_IRQ_VCHG_TMR_FAULT:
157 __set_charger(info, 0);
158 dev_dbg(chip->dev, "Safe timer is expired\n");
159 break;
160 case MAX8925_IRQ_VCHG_RST:
161 __set_charger(info, 0);
162 dev_dbg(chip->dev, "Charger is reset\n");
163 break;
164 }
165 return IRQ_HANDLED;
166}
167
168static int start_measure(struct max8925_power_info *info, int type)
169{
170 unsigned char buf[2] = {0, 0};
171 int meas_reg = 0, ret;
172
173 switch (type) {
174 case MEASURE_VCHG:
175 meas_reg = MAX8925_ADC_VCHG;
176 break;
177 case MEASURE_VBBATT:
178 meas_reg = MAX8925_ADC_VBBATT;
179 break;
180 case MEASURE_VMBATT:
181 meas_reg = MAX8925_ADC_VMBATT;
182 break;
183 case MEASURE_ISNS:
184 meas_reg = MAX8925_ADC_ISNS;
185 break;
186 default:
187 return -EINVAL;
188 }
189
190 max8925_bulk_read(info->adc, meas_reg, 2, buf);
191 ret = (buf[0] << 4) | (buf[1] >> 4);
192
193 return ret;
194}
195
196static int max8925_ac_get_prop(struct power_supply *psy,
197 enum power_supply_property psp,
198 union power_supply_propval *val)
199{
200 struct max8925_power_info *info = dev_get_drvdata(psy->dev->parent);
201 int ret = 0;
202
203 switch (psp) {
204 case POWER_SUPPLY_PROP_ONLINE:
205 val->intval = info->ac_online;
206 break;
207 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
208 if (info->ac_online) {
209 ret = start_measure(info, MEASURE_VCHG);
210 if (ret >= 0) {
211 val->intval = ret << 1; /* unit is mV */
212 goto out;
213 }
214 }
215 ret = -ENODATA;
216 break;
217 default:
218 ret = -ENODEV;
219 break;
220 }
221out:
222 return ret;
223}
224
225static enum power_supply_property max8925_ac_props[] = {
226 POWER_SUPPLY_PROP_ONLINE,
227 POWER_SUPPLY_PROP_VOLTAGE_NOW,
228};
229
230static int max8925_usb_get_prop(struct power_supply *psy,
231 enum power_supply_property psp,
232 union power_supply_propval *val)
233{
234 struct max8925_power_info *info = dev_get_drvdata(psy->dev->parent);
235 int ret = 0;
236
237 switch (psp) {
238 case POWER_SUPPLY_PROP_ONLINE:
239 val->intval = info->usb_online;
240 break;
241 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
242 if (info->usb_online) {
243 ret = start_measure(info, MEASURE_VCHG);
244 if (ret >= 0) {
245 val->intval = ret << 1; /* unit is mV */
246 goto out;
247 }
248 }
249 ret = -ENODATA;
250 break;
251 default:
252 ret = -ENODEV;
253 break;
254 }
255out:
256 return ret;
257}
258
259static enum power_supply_property max8925_usb_props[] = {
260 POWER_SUPPLY_PROP_ONLINE,
261 POWER_SUPPLY_PROP_VOLTAGE_NOW,
262};
263
264static int max8925_bat_get_prop(struct power_supply *psy,
265 enum power_supply_property psp,
266 union power_supply_propval *val)
267{
268 struct max8925_power_info *info = dev_get_drvdata(psy->dev->parent);
269 long long int tmp = 0;
270 int ret = 0;
271
272 switch (psp) {
273 case POWER_SUPPLY_PROP_ONLINE:
274 val->intval = info->bat_online;
275 break;
276 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
277 if (info->bat_online) {
278 ret = start_measure(info, MEASURE_VMBATT);
279 if (ret >= 0) {
280 val->intval = ret << 1; /* unit is mV */
281 ret = 0;
282 break;
283 }
284 }
285 ret = -ENODATA;
286 break;
287 case POWER_SUPPLY_PROP_CURRENT_NOW:
288 if (info->bat_online) {
289 ret = start_measure(info, MEASURE_ISNS);
290 if (ret >= 0) {
291 tmp = (long long int)ret * 6250 / 4096 - 3125;
292 ret = (int)tmp;
293 val->intval = 0;
294 if (ret > 0)
295 val->intval = ret; /* unit is mA */
296 ret = 0;
297 break;
298 }
299 }
300 ret = -ENODATA;
301 break;
302 case POWER_SUPPLY_PROP_CHARGE_TYPE:
303 if (!info->bat_online) {
304 ret = -ENODATA;
305 break;
306 }
307 ret = max8925_reg_read(info->gpm, MAX8925_CHG_STATUS);
308 ret = (ret & MAX8925_CHG_STAT_MODE_MASK) >> 2;
309 switch (ret) {
310 case 1:
311 val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST;
312 break;
313 case 0:
314 case 2:
315 val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
316 break;
317 case 3:
318 val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
319 break;
320 }
321 ret = 0;
322 break;
323 case POWER_SUPPLY_PROP_STATUS:
324 if (!info->bat_online) {
325 ret = -ENODATA;
326 break;
327 }
328 ret = max8925_reg_read(info->gpm, MAX8925_CHG_STATUS);
329 if (info->usb_online || info->ac_online) {
330 val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
331 if (ret & MAX8925_CHG_STAT_EN_MASK)
332 val->intval = POWER_SUPPLY_STATUS_CHARGING;
333 } else
334 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
335 ret = 0;
336 break;
337 default:
338 ret = -ENODEV;
339 break;
340 }
341 return ret;
342}
343
344static enum power_supply_property max8925_battery_props[] = {
345 POWER_SUPPLY_PROP_ONLINE,
346 POWER_SUPPLY_PROP_VOLTAGE_NOW,
347 POWER_SUPPLY_PROP_CURRENT_NOW,
348 POWER_SUPPLY_PROP_CHARGE_TYPE,
349 POWER_SUPPLY_PROP_STATUS,
350};
351
352#define REQUEST_IRQ(_irq, _name) \
353do { \
354 ret = request_threaded_irq(chip->irq_base + _irq, NULL, \
355 max8925_charger_handler, \
356 IRQF_ONESHOT, _name, info); \
357 if (ret) \
358 dev_err(chip->dev, "Failed to request IRQ #%d: %d\n", \
359 _irq, ret); \
360} while (0)
361
362static __devinit int max8925_init_charger(struct max8925_chip *chip,
363 struct max8925_power_info *info)
364{
365 int ret;
366
367 REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_OVP, "ac-ovp");
368 REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_F, "ac-remove");
369 REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_R, "ac-insert");
370 REQUEST_IRQ(MAX8925_IRQ_VCHG_USB_OVP, "usb-ovp");
371 REQUEST_IRQ(MAX8925_IRQ_VCHG_USB_F, "usb-remove");
372 REQUEST_IRQ(MAX8925_IRQ_VCHG_USB_R, "usb-insert");
373 REQUEST_IRQ(MAX8925_IRQ_VCHG_THM_OK_R, "batt-temp-in-range");
374 REQUEST_IRQ(MAX8925_IRQ_VCHG_THM_OK_F, "batt-temp-out-range");
375 REQUEST_IRQ(MAX8925_IRQ_VCHG_SYSLOW_F, "vsys-high");
376 REQUEST_IRQ(MAX8925_IRQ_VCHG_SYSLOW_R, "vsys-low");
377 REQUEST_IRQ(MAX8925_IRQ_VCHG_RST, "charger-reset");
378 REQUEST_IRQ(MAX8925_IRQ_VCHG_DONE, "charger-done");
379 REQUEST_IRQ(MAX8925_IRQ_VCHG_TOPOFF, "charger-topoff");
380 REQUEST_IRQ(MAX8925_IRQ_VCHG_TMR_FAULT, "charger-timer-expire");
381
382 info->ac_online = 0;
383 info->usb_online = 0;
384 info->bat_online = 0;
385 ret = max8925_reg_read(info->gpm, MAX8925_CHG_STATUS);
386 if (ret >= 0) {
387 /*
388 * If battery detection is enabled, ID pin of battery is
389 * connected to MBDET pin of MAX8925. It could be used to
390 * detect battery presence.
391 * Otherwise, we have to assume that battery is always on.
392 */
393 if (info->batt_detect)
394 info->bat_online = (ret & MAX8925_CHG_MBDET) ? 0 : 1;
395 else
396 info->bat_online = 1;
397 if (ret & MAX8925_CHG_AC_RANGE_MASK)
398 info->ac_online = 1;
399 else
400 info->ac_online = 0;
401 }
402 /* disable charge */
403 max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 1 << 7, 1 << 7);
404 /* set charging current in charge topoff mode */
405 max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 3 << 5,
406 info->topoff_threshold << 5);
407 /* set charing current in fast charge mode */
408 max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 7, info->fast_charge);
409
410 return 0;
411}
412
413static __devexit int max8925_deinit_charger(struct max8925_power_info *info)
414{
415 struct max8925_chip *chip = info->chip;
416 int irq;
417
418 irq = chip->irq_base + MAX8925_IRQ_VCHG_DC_OVP;
419 for (; irq <= chip->irq_base + MAX8925_IRQ_VCHG_TMR_FAULT; irq++)
420 free_irq(irq, info);
421
422 return 0;
423}
424
425static __devinit int max8925_power_probe(struct platform_device *pdev)
426{
427 struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
428 struct max8925_platform_data *max8925_pdata;
429 struct max8925_power_pdata *pdata = NULL;
430 struct max8925_power_info *info;
431 int ret;
432
433 if (pdev->dev.parent->platform_data) {
434 max8925_pdata = pdev->dev.parent->platform_data;
435 pdata = max8925_pdata->power;
436 }
437
438 if (!pdata) {
439 dev_err(&pdev->dev, "platform data isn't assigned to "
440 "power supply\n");
441 return -EINVAL;
442 }
443
444 info = kzalloc(sizeof(struct max8925_power_info), GFP_KERNEL);
445 if (!info)
446 return -ENOMEM;
447 info->chip = chip;
448 info->gpm = chip->i2c;
449 info->adc = chip->adc;
450
451 info->ac.name = "max8925-ac";
452 info->ac.type = POWER_SUPPLY_TYPE_MAINS;
453 info->ac.properties = max8925_ac_props;
454 info->ac.num_properties = ARRAY_SIZE(max8925_ac_props);
455 info->ac.get_property = max8925_ac_get_prop;
456 ret = power_supply_register(&pdev->dev, &info->ac);
457 if (ret)
458 goto out;
459 info->ac.dev->parent = &pdev->dev;
460
461 info->usb.name = "max8925-usb";
462 info->usb.type = POWER_SUPPLY_TYPE_USB;
463 info->usb.properties = max8925_usb_props;
464 info->usb.num_properties = ARRAY_SIZE(max8925_usb_props);
465 info->usb.get_property = max8925_usb_get_prop;
466 ret = power_supply_register(&pdev->dev, &info->usb);
467 if (ret)
468 goto out_usb;
469 info->usb.dev->parent = &pdev->dev;
470
471 info->battery.name = "max8925-battery";
472 info->battery.type = POWER_SUPPLY_TYPE_BATTERY;
473 info->battery.properties = max8925_battery_props;
474 info->battery.num_properties = ARRAY_SIZE(max8925_battery_props);
475 info->battery.get_property = max8925_bat_get_prop;
476 ret = power_supply_register(&pdev->dev, &info->battery);
477 if (ret)
478 goto out_battery;
479 info->battery.dev->parent = &pdev->dev;
480
481 info->batt_detect = pdata->batt_detect;
482 info->topoff_threshold = pdata->topoff_threshold;
483 info->fast_charge = pdata->fast_charge;
484 info->set_charger = pdata->set_charger;
485 dev_set_drvdata(&pdev->dev, info);
486 platform_set_drvdata(pdev, info);
487
488 max8925_init_charger(chip, info);
489 return 0;
490out_battery:
491 power_supply_unregister(&info->battery);
492out_usb:
493 power_supply_unregister(&info->ac);
494out:
495 kfree(info);
496 return ret;
497}
498
499static __devexit int max8925_power_remove(struct platform_device *pdev)
500{
501 struct max8925_power_info *info = platform_get_drvdata(pdev);
502
503 if (info) {
504 power_supply_unregister(&info->ac);
505 power_supply_unregister(&info->usb);
506 power_supply_unregister(&info->battery);
507 max8925_deinit_charger(info);
508 kfree(info);
509 }
510 return 0;
511}
512
513static struct platform_driver max8925_power_driver = {
514 .probe = max8925_power_probe,
515 .remove = __devexit_p(max8925_power_remove),
516 .driver = {
517 .name = "max8925-power",
518 },
519};
520
521static int __init max8925_power_init(void)
522{
523 return platform_driver_register(&max8925_power_driver);
524}
525module_init(max8925_power_init);
526
527static void __exit max8925_power_exit(void)
528{
529 platform_driver_unregister(&max8925_power_driver);
530}
531module_exit(max8925_power_exit);
532
533MODULE_LICENSE("GPL");
534MODULE_DESCRIPTION("Power supply driver for MAX8925");
535MODULE_ALIAS("platform:max8925-power");
diff --git a/drivers/power/pcf50633-charger.c b/drivers/power/pcf50633-charger.c
index e8b278f71781..066f994e6fe5 100644
--- a/drivers/power/pcf50633-charger.c
+++ b/drivers/power/pcf50633-charger.c
@@ -16,6 +16,7 @@
16 16
17#include <linux/kernel.h> 17#include <linux/kernel.h>
18#include <linux/module.h> 18#include <linux/module.h>
19#include <linux/slab.h>
19#include <linux/init.h> 20#include <linux/init.h>
20#include <linux/types.h> 21#include <linux/types.h>
21#include <linux/device.h> 22#include <linux/device.h>
@@ -29,15 +30,12 @@
29struct pcf50633_mbc { 30struct pcf50633_mbc {
30 struct pcf50633 *pcf; 31 struct pcf50633 *pcf;
31 32
32 int adapter_active;
33 int adapter_online; 33 int adapter_online;
34 int usb_active;
35 int usb_online; 34 int usb_online;
36 35
37 struct power_supply usb; 36 struct power_supply usb;
38 struct power_supply adapter; 37 struct power_supply adapter;
39 38 struct power_supply ac;
40 struct delayed_work charging_restart_work;
41}; 39};
42 40
43int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma) 41int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma)
@@ -47,16 +45,21 @@ int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma)
47 u8 bits; 45 u8 bits;
48 int charging_start = 1; 46 int charging_start = 1;
49 u8 mbcs2, chgmod; 47 u8 mbcs2, chgmod;
48 unsigned int mbcc5;
50 49
51 if (ma >= 1000) 50 if (ma >= 1000) {
52 bits = PCF50633_MBCC7_USB_1000mA; 51 bits = PCF50633_MBCC7_USB_1000mA;
53 else if (ma >= 500) 52 ma = 1000;
53 } else if (ma >= 500) {
54 bits = PCF50633_MBCC7_USB_500mA; 54 bits = PCF50633_MBCC7_USB_500mA;
55 else if (ma >= 100) 55 ma = 500;
56 } else if (ma >= 100) {
56 bits = PCF50633_MBCC7_USB_100mA; 57 bits = PCF50633_MBCC7_USB_100mA;
57 else { 58 ma = 100;
59 } else {
58 bits = PCF50633_MBCC7_USB_SUSPEND; 60 bits = PCF50633_MBCC7_USB_SUSPEND;
59 charging_start = 0; 61 charging_start = 0;
62 ma = 0;
60 } 63 }
61 64
62 ret = pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC7, 65 ret = pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC7,
@@ -66,21 +69,40 @@ int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma)
66 else 69 else
67 dev_info(pcf->dev, "usb curlim to %d mA\n", ma); 70 dev_info(pcf->dev, "usb curlim to %d mA\n", ma);
68 71
69 /* Manual charging start */ 72 /*
70 mbcs2 = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2); 73 * We limit the charging current to be the USB current limit.
74 * The reason is that on pcf50633, when it enters PMU Standby mode,
75 * which it does when the device goes "off", the USB current limit
76 * reverts to the variant default. In at least one common case, that
77 * default is 500mA. By setting the charging current to be the same
78 * as the USB limit we set here before PMU standby, we enforce it only
79 * using the correct amount of current even when the USB current limit
80 * gets reset to the wrong thing
81 */
82
83 if (mbc->pcf->pdata->charger_reference_current_ma) {
84 mbcc5 = (ma << 8) / mbc->pcf->pdata->charger_reference_current_ma;
85 if (mbcc5 > 255)
86 mbcc5 = 255;
87 pcf50633_reg_write(mbc->pcf, PCF50633_REG_MBCC5, mbcc5);
88 }
89
90 mbcs2 = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCS2);
71 chgmod = (mbcs2 & PCF50633_MBCS2_MBC_MASK); 91 chgmod = (mbcs2 & PCF50633_MBCS2_MBC_MASK);
72 92
73 /* If chgmod == BATFULL, setting chgena has no effect. 93 /* If chgmod == BATFULL, setting chgena has no effect.
74 * We need to set resume instead. 94 * Datasheet says we need to set resume instead but when autoresume is
95 * used resume doesn't work. Clear and set chgena instead.
75 */ 96 */
76 if (chgmod != PCF50633_MBCS2_MBC_BAT_FULL) 97 if (chgmod != PCF50633_MBCS2_MBC_BAT_FULL)
77 pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC1, 98 pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC1,
78 PCF50633_MBCC1_CHGENA, PCF50633_MBCC1_CHGENA); 99 PCF50633_MBCC1_CHGENA, PCF50633_MBCC1_CHGENA);
79 else 100 else {
101 pcf50633_reg_clear_bits(pcf, PCF50633_REG_MBCC1,
102 PCF50633_MBCC1_CHGENA);
80 pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC1, 103 pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC1,
81 PCF50633_MBCC1_RESUME, PCF50633_MBCC1_RESUME); 104 PCF50633_MBCC1_CHGENA, PCF50633_MBCC1_CHGENA);
82 105 }
83 mbc->usb_active = charging_start;
84 106
85 power_supply_changed(&mbc->usb); 107 power_supply_changed(&mbc->usb);
86 108
@@ -92,20 +114,44 @@ int pcf50633_mbc_get_status(struct pcf50633 *pcf)
92{ 114{
93 struct pcf50633_mbc *mbc = platform_get_drvdata(pcf->mbc_pdev); 115 struct pcf50633_mbc *mbc = platform_get_drvdata(pcf->mbc_pdev);
94 int status = 0; 116 int status = 0;
117 u8 chgmod;
118
119 if (!mbc)
120 return 0;
121
122 chgmod = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCS2)
123 & PCF50633_MBCS2_MBC_MASK;
95 124
96 if (mbc->usb_online) 125 if (mbc->usb_online)
97 status |= PCF50633_MBC_USB_ONLINE; 126 status |= PCF50633_MBC_USB_ONLINE;
98 if (mbc->usb_active) 127 if (chgmod == PCF50633_MBCS2_MBC_USB_PRE ||
128 chgmod == PCF50633_MBCS2_MBC_USB_PRE_WAIT ||
129 chgmod == PCF50633_MBCS2_MBC_USB_FAST ||
130 chgmod == PCF50633_MBCS2_MBC_USB_FAST_WAIT)
99 status |= PCF50633_MBC_USB_ACTIVE; 131 status |= PCF50633_MBC_USB_ACTIVE;
100 if (mbc->adapter_online) 132 if (mbc->adapter_online)
101 status |= PCF50633_MBC_ADAPTER_ONLINE; 133 status |= PCF50633_MBC_ADAPTER_ONLINE;
102 if (mbc->adapter_active) 134 if (chgmod == PCF50633_MBCS2_MBC_ADP_PRE ||
135 chgmod == PCF50633_MBCS2_MBC_ADP_PRE_WAIT ||
136 chgmod == PCF50633_MBCS2_MBC_ADP_FAST ||
137 chgmod == PCF50633_MBCS2_MBC_ADP_FAST_WAIT)
103 status |= PCF50633_MBC_ADAPTER_ACTIVE; 138 status |= PCF50633_MBC_ADAPTER_ACTIVE;
104 139
105 return status; 140 return status;
106} 141}
107EXPORT_SYMBOL_GPL(pcf50633_mbc_get_status); 142EXPORT_SYMBOL_GPL(pcf50633_mbc_get_status);
108 143
144int pcf50633_mbc_get_usb_online_status(struct pcf50633 *pcf)
145{
146 struct pcf50633_mbc *mbc = platform_get_drvdata(pcf->mbc_pdev);
147
148 if (!mbc)
149 return 0;
150
151 return mbc->usb_online;
152}
153EXPORT_SYMBOL_GPL(pcf50633_mbc_get_usb_online_status);
154
109static ssize_t 155static ssize_t
110show_chgmode(struct device *dev, struct device_attribute *attr, char *buf) 156show_chgmode(struct device *dev, struct device_attribute *attr, char *buf)
111{ 157{
@@ -156,9 +202,55 @@ static ssize_t set_usblim(struct device *dev,
156 202
157static DEVICE_ATTR(usb_curlim, S_IRUGO | S_IWUSR, show_usblim, set_usblim); 203static DEVICE_ATTR(usb_curlim, S_IRUGO | S_IWUSR, show_usblim, set_usblim);
158 204
205static ssize_t
206show_chglim(struct device *dev, struct device_attribute *attr, char *buf)
207{
208 struct pcf50633_mbc *mbc = dev_get_drvdata(dev);
209 u8 mbcc5 = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCC5);
210 unsigned int ma;
211
212 if (!mbc->pcf->pdata->charger_reference_current_ma)
213 return -ENODEV;
214
215 ma = (mbc->pcf->pdata->charger_reference_current_ma * mbcc5) >> 8;
216
217 return sprintf(buf, "%u\n", ma);
218}
219
220static ssize_t set_chglim(struct device *dev,
221 struct device_attribute *attr, const char *buf, size_t count)
222{
223 struct pcf50633_mbc *mbc = dev_get_drvdata(dev);
224 unsigned long ma;
225 unsigned int mbcc5;
226 int ret;
227
228 if (!mbc->pcf->pdata->charger_reference_current_ma)
229 return -ENODEV;
230
231 ret = strict_strtoul(buf, 10, &ma);
232 if (ret)
233 return -EINVAL;
234
235 mbcc5 = (ma << 8) / mbc->pcf->pdata->charger_reference_current_ma;
236 if (mbcc5 > 255)
237 mbcc5 = 255;
238 pcf50633_reg_write(mbc->pcf, PCF50633_REG_MBCC5, mbcc5);
239
240 return count;
241}
242
243/*
244 * This attribute allows to change MBC charging limit on the fly
245 * independently of usb current limit. It also gets set automatically every
246 * time usb current limit is changed.
247 */
248static DEVICE_ATTR(chg_curlim, S_IRUGO | S_IWUSR, show_chglim, set_chglim);
249
159static struct attribute *pcf50633_mbc_sysfs_entries[] = { 250static struct attribute *pcf50633_mbc_sysfs_entries[] = {
160 &dev_attr_chgmode.attr, 251 &dev_attr_chgmode.attr,
161 &dev_attr_usb_curlim.attr, 252 &dev_attr_usb_curlim.attr,
253 &dev_attr_chg_curlim.attr,
162 NULL, 254 NULL,
163}; 255};
164 256
@@ -167,76 +259,26 @@ static struct attribute_group mbc_attr_group = {
167 .attrs = pcf50633_mbc_sysfs_entries, 259 .attrs = pcf50633_mbc_sysfs_entries,
168}; 260};
169 261
170/* MBC state machine switches into charging mode when the battery voltage
171 * falls below 96% of a battery float voltage. But the voltage drop in Li-ion
172 * batteries is marginal(1~2 %) till about 80% of its capacity - which means,
173 * after a BATFULL, charging won't be restarted until 80%.
174 *
175 * This work_struct function restarts charging at regular intervals to make
176 * sure we don't discharge too much
177 */
178
179static void pcf50633_mbc_charging_restart(struct work_struct *work)
180{
181 struct pcf50633_mbc *mbc;
182 u8 mbcs2, chgmod;
183
184 mbc = container_of(work, struct pcf50633_mbc,
185 charging_restart_work.work);
186
187 mbcs2 = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCS2);
188 chgmod = (mbcs2 & PCF50633_MBCS2_MBC_MASK);
189
190 if (chgmod != PCF50633_MBCS2_MBC_BAT_FULL)
191 return;
192
193 /* Restart charging */
194 pcf50633_reg_set_bit_mask(mbc->pcf, PCF50633_REG_MBCC1,
195 PCF50633_MBCC1_RESUME, PCF50633_MBCC1_RESUME);
196 mbc->usb_active = 1;
197 power_supply_changed(&mbc->usb);
198
199 dev_info(mbc->pcf->dev, "Charging restarted\n");
200}
201
202static void 262static void
203pcf50633_mbc_irq_handler(int irq, void *data) 263pcf50633_mbc_irq_handler(int irq, void *data)
204{ 264{
205 struct pcf50633_mbc *mbc = data; 265 struct pcf50633_mbc *mbc = data;
206 int chg_restart_interval =
207 mbc->pcf->pdata->charging_restart_interval;
208 266
209 /* USB */ 267 /* USB */
210 if (irq == PCF50633_IRQ_USBINS) { 268 if (irq == PCF50633_IRQ_USBINS) {
211 mbc->usb_online = 1; 269 mbc->usb_online = 1;
212 } else if (irq == PCF50633_IRQ_USBREM) { 270 } else if (irq == PCF50633_IRQ_USBREM) {
213 mbc->usb_online = 0; 271 mbc->usb_online = 0;
214 mbc->usb_active = 0;
215 pcf50633_mbc_usb_curlim_set(mbc->pcf, 0); 272 pcf50633_mbc_usb_curlim_set(mbc->pcf, 0);
216 cancel_delayed_work_sync(&mbc->charging_restart_work);
217 } 273 }
218 274
219 /* Adapter */ 275 /* Adapter */
220 if (irq == PCF50633_IRQ_ADPINS) { 276 if (irq == PCF50633_IRQ_ADPINS)
221 mbc->adapter_online = 1; 277 mbc->adapter_online = 1;
222 mbc->adapter_active = 1; 278 else if (irq == PCF50633_IRQ_ADPREM)
223 } else if (irq == PCF50633_IRQ_ADPREM) {
224 mbc->adapter_online = 0; 279 mbc->adapter_online = 0;
225 mbc->adapter_active = 0;
226 }
227
228 if (irq == PCF50633_IRQ_BATFULL) {
229 mbc->usb_active = 0;
230 mbc->adapter_active = 0;
231
232 if (chg_restart_interval > 0)
233 schedule_delayed_work(&mbc->charging_restart_work,
234 chg_restart_interval);
235 } else if (irq == PCF50633_IRQ_USBLIMON)
236 mbc->usb_active = 0;
237 else if (irq == PCF50633_IRQ_USBLIMOFF)
238 mbc->usb_active = 1;
239 280
281 power_supply_changed(&mbc->ac);
240 power_supply_changed(&mbc->usb); 282 power_supply_changed(&mbc->usb);
241 power_supply_changed(&mbc->adapter); 283 power_supply_changed(&mbc->adapter);
242 284
@@ -269,10 +311,34 @@ static int usb_get_property(struct power_supply *psy,
269{ 311{
270 struct pcf50633_mbc *mbc = container_of(psy, struct pcf50633_mbc, usb); 312 struct pcf50633_mbc *mbc = container_of(psy, struct pcf50633_mbc, usb);
271 int ret = 0; 313 int ret = 0;
314 u8 usblim = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCC7) &
315 PCF50633_MBCC7_USB_MASK;
272 316
273 switch (psp) { 317 switch (psp) {
274 case POWER_SUPPLY_PROP_ONLINE: 318 case POWER_SUPPLY_PROP_ONLINE:
275 val->intval = mbc->usb_online; 319 val->intval = mbc->usb_online &&
320 (usblim <= PCF50633_MBCC7_USB_500mA);
321 break;
322 default:
323 ret = -EINVAL;
324 break;
325 }
326 return ret;
327}
328
329static int ac_get_property(struct power_supply *psy,
330 enum power_supply_property psp,
331 union power_supply_propval *val)
332{
333 struct pcf50633_mbc *mbc = container_of(psy, struct pcf50633_mbc, ac);
334 int ret = 0;
335 u8 usblim = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCC7) &
336 PCF50633_MBCC7_USB_MASK;
337
338 switch (psp) {
339 case POWER_SUPPLY_PROP_ONLINE:
340 val->intval = mbc->usb_online &&
341 (usblim == PCF50633_MBCC7_USB_1000mA);
276 break; 342 break;
277 default: 343 default:
278 ret = -EINVAL; 344 ret = -EINVAL;
@@ -303,7 +369,6 @@ static const u8 mbc_irq_handlers[] = {
303static int __devinit pcf50633_mbc_probe(struct platform_device *pdev) 369static int __devinit pcf50633_mbc_probe(struct platform_device *pdev)
304{ 370{
305 struct pcf50633_mbc *mbc; 371 struct pcf50633_mbc *mbc;
306 struct pcf50633_subdev_pdata *pdata = pdev->dev.platform_data;
307 int ret; 372 int ret;
308 int i; 373 int i;
309 u8 mbcs1; 374 u8 mbcs1;
@@ -313,7 +378,7 @@ static int __devinit pcf50633_mbc_probe(struct platform_device *pdev)
313 return -ENOMEM; 378 return -ENOMEM;
314 379
315 platform_set_drvdata(pdev, mbc); 380 platform_set_drvdata(pdev, mbc);
316 mbc->pcf = pdata->pcf; 381 mbc->pcf = dev_to_pcf50633(pdev->dev.parent);
317 382
318 /* Set up IRQ handlers */ 383 /* Set up IRQ handlers */
319 for (i = 0; i < ARRAY_SIZE(mbc_irq_handlers); i++) 384 for (i = 0; i < ARRAY_SIZE(mbc_irq_handlers); i++)
@@ -337,6 +402,14 @@ static int __devinit pcf50633_mbc_probe(struct platform_device *pdev)
337 mbc->usb.supplied_to = mbc->pcf->pdata->batteries; 402 mbc->usb.supplied_to = mbc->pcf->pdata->batteries;
338 mbc->usb.num_supplicants = mbc->pcf->pdata->num_batteries; 403 mbc->usb.num_supplicants = mbc->pcf->pdata->num_batteries;
339 404
405 mbc->ac.name = "ac";
406 mbc->ac.type = POWER_SUPPLY_TYPE_MAINS;
407 mbc->ac.properties = power_props;
408 mbc->ac.num_properties = ARRAY_SIZE(power_props);
409 mbc->ac.get_property = ac_get_property;
410 mbc->ac.supplied_to = mbc->pcf->pdata->batteries;
411 mbc->ac.num_supplicants = mbc->pcf->pdata->num_batteries;
412
340 ret = power_supply_register(&pdev->dev, &mbc->adapter); 413 ret = power_supply_register(&pdev->dev, &mbc->adapter);
341 if (ret) { 414 if (ret) {
342 dev_err(mbc->pcf->dev, "failed to register adapter\n"); 415 dev_err(mbc->pcf->dev, "failed to register adapter\n");
@@ -352,8 +425,14 @@ static int __devinit pcf50633_mbc_probe(struct platform_device *pdev)
352 return ret; 425 return ret;
353 } 426 }
354 427
355 INIT_DELAYED_WORK(&mbc->charging_restart_work, 428 ret = power_supply_register(&pdev->dev, &mbc->ac);
356 pcf50633_mbc_charging_restart); 429 if (ret) {
430 dev_err(mbc->pcf->dev, "failed to register ac\n");
431 power_supply_unregister(&mbc->adapter);
432 power_supply_unregister(&mbc->usb);
433 kfree(mbc);
434 return ret;
435 }
357 436
358 ret = sysfs_create_group(&pdev->dev.kobj, &mbc_attr_group); 437 ret = sysfs_create_group(&pdev->dev.kobj, &mbc_attr_group);
359 if (ret) 438 if (ret)
@@ -379,8 +458,7 @@ static int __devexit pcf50633_mbc_remove(struct platform_device *pdev)
379 458
380 power_supply_unregister(&mbc->usb); 459 power_supply_unregister(&mbc->usb);
381 power_supply_unregister(&mbc->adapter); 460 power_supply_unregister(&mbc->adapter);
382 461 power_supply_unregister(&mbc->ac);
383 cancel_delayed_work_sync(&mbc->charging_restart_work);
384 462
385 kfree(mbc); 463 kfree(mbc);
386 464
diff --git a/drivers/power/pmu_battery.c b/drivers/power/pmu_battery.c
index 9346a862f1f2..023d24993b87 100644
--- a/drivers/power/pmu_battery.c
+++ b/drivers/power/pmu_battery.c
@@ -14,6 +14,7 @@
14#include <linux/power_supply.h> 14#include <linux/power_supply.h>
15#include <linux/adb.h> 15#include <linux/adb.h>
16#include <linux/pmu.h> 16#include <linux/pmu.h>
17#include <linux/slab.h>
17 18
18static struct pmu_battery_dev { 19static struct pmu_battery_dev {
19 struct power_supply bat; 20 struct power_supply bat;
@@ -89,6 +90,8 @@ static int pmu_bat_get_property(struct power_supply *psy,
89 case POWER_SUPPLY_PROP_STATUS: 90 case POWER_SUPPLY_PROP_STATUS:
90 if (pbi->flags & PMU_BATT_CHARGING) 91 if (pbi->flags & PMU_BATT_CHARGING)
91 val->intval = POWER_SUPPLY_STATUS_CHARGING; 92 val->intval = POWER_SUPPLY_STATUS_CHARGING;
93 else if (pmu_power_flags & PMU_PWR_AC_PRESENT)
94 val->intval = POWER_SUPPLY_STATUS_FULL;
92 else 95 else
93 val->intval = POWER_SUPPLY_STATUS_DISCHARGING; 96 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
94 break; 97 break;
diff --git a/drivers/power/power_supply_leds.c b/drivers/power/power_supply_leds.c
index 2dece40c544f..031a554837f7 100644
--- a/drivers/power/power_supply_leds.c
+++ b/drivers/power/power_supply_leds.c
@@ -12,6 +12,7 @@
12 12
13#include <linux/kernel.h> 13#include <linux/kernel.h>
14#include <linux/power_supply.h> 14#include <linux/power_supply.h>
15#include <linux/slab.h>
15 16
16#include "power_supply.h" 17#include "power_supply.h"
17 18
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
index 08144393d64b..5b6e352ac7c1 100644
--- a/drivers/power/power_supply_sysfs.c
+++ b/drivers/power/power_supply_sysfs.c
@@ -13,6 +13,7 @@
13 13
14#include <linux/ctype.h> 14#include <linux/ctype.h>
15#include <linux/power_supply.h> 15#include <linux/power_supply.h>
16#include <linux/slab.h>
16 17
17#include "power_supply.h" 18#include "power_supply.h"
18 19
@@ -65,7 +66,10 @@ static ssize_t power_supply_show_property(struct device *dev,
65 ret = psy->get_property(psy, off, &value); 66 ret = psy->get_property(psy, off, &value);
66 67
67 if (ret < 0) { 68 if (ret < 0) {
68 if (ret != -ENODEV) 69 if (ret == -ENODATA)
70 dev_dbg(dev, "driver has no data for `%s' property\n",
71 attr->attr.name);
72 else if (ret != -ENODEV)
69 dev_err(dev, "driver failed to report `%s' property\n", 73 dev_err(dev, "driver failed to report `%s' property\n",
70 attr->attr.name); 74 attr->attr.name);
71 return ret; 75 return ret;
@@ -96,6 +100,7 @@ static struct device_attribute power_supply_attrs[] = {
96 POWER_SUPPLY_ATTR(present), 100 POWER_SUPPLY_ATTR(present),
97 POWER_SUPPLY_ATTR(online), 101 POWER_SUPPLY_ATTR(online),
98 POWER_SUPPLY_ATTR(technology), 102 POWER_SUPPLY_ATTR(technology),
103 POWER_SUPPLY_ATTR(cycle_count),
99 POWER_SUPPLY_ATTR(voltage_max), 104 POWER_SUPPLY_ATTR(voltage_max),
100 POWER_SUPPLY_ATTR(voltage_min), 105 POWER_SUPPLY_ATTR(voltage_min),
101 POWER_SUPPLY_ATTR(voltage_max_design), 106 POWER_SUPPLY_ATTR(voltage_max_design),
diff --git a/drivers/power/wm831x_backup.c b/drivers/power/wm831x_backup.c
new file mode 100644
index 000000000000..0fd130d80f5d
--- /dev/null
+++ b/drivers/power/wm831x_backup.c
@@ -0,0 +1,234 @@
1/*
2 * Backup battery driver for Wolfson Microelectronics wm831x PMICs
3 *
4 * Copyright 2009 Wolfson Microelectronics PLC.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/module.h>
12#include <linux/err.h>
13#include <linux/platform_device.h>
14#include <linux/power_supply.h>
15#include <linux/slab.h>
16
17#include <linux/mfd/wm831x/core.h>
18#include <linux/mfd/wm831x/auxadc.h>
19#include <linux/mfd/wm831x/pmu.h>
20#include <linux/mfd/wm831x/pdata.h>
21
22struct wm831x_backup {
23 struct wm831x *wm831x;
24 struct power_supply backup;
25};
26
27static int wm831x_backup_read_voltage(struct wm831x *wm831x,
28 enum wm831x_auxadc src,
29 union power_supply_propval *val)
30{
31 int ret;
32
33 ret = wm831x_auxadc_read_uv(wm831x, src);
34 if (ret >= 0)
35 val->intval = ret;
36
37 return ret;
38}
39
40/*********************************************************************
41 * Backup supply properties
42 *********************************************************************/
43
44static void wm831x_config_backup(struct wm831x *wm831x)
45{
46 struct wm831x_pdata *wm831x_pdata = wm831x->dev->platform_data;
47 struct wm831x_backup_pdata *pdata;
48 int ret, reg;
49
50 if (!wm831x_pdata || !wm831x_pdata->backup) {
51 dev_warn(wm831x->dev,
52 "No backup battery charger configuration\n");
53 return;
54 }
55
56 pdata = wm831x_pdata->backup;
57
58 reg = 0;
59
60 if (pdata->charger_enable)
61 reg |= WM831X_BKUP_CHG_ENA | WM831X_BKUP_BATT_DET_ENA;
62 if (pdata->no_constant_voltage)
63 reg |= WM831X_BKUP_CHG_MODE;
64
65 switch (pdata->vlim) {
66 case 2500:
67 break;
68 case 3100:
69 reg |= WM831X_BKUP_CHG_VLIM;
70 break;
71 default:
72 dev_err(wm831x->dev, "Invalid backup voltage limit %dmV\n",
73 pdata->vlim);
74 }
75
76 switch (pdata->ilim) {
77 case 100:
78 break;
79 case 200:
80 reg |= 1;
81 break;
82 case 300:
83 reg |= 2;
84 break;
85 case 400:
86 reg |= 3;
87 break;
88 default:
89 dev_err(wm831x->dev, "Invalid backup current limit %duA\n",
90 pdata->ilim);
91 }
92
93 ret = wm831x_reg_unlock(wm831x);
94 if (ret != 0) {
95 dev_err(wm831x->dev, "Failed to unlock registers: %d\n", ret);
96 return;
97 }
98
99 ret = wm831x_set_bits(wm831x, WM831X_BACKUP_CHARGER_CONTROL,
100 WM831X_BKUP_CHG_ENA_MASK |
101 WM831X_BKUP_CHG_MODE_MASK |
102 WM831X_BKUP_BATT_DET_ENA_MASK |
103 WM831X_BKUP_CHG_VLIM_MASK |
104 WM831X_BKUP_CHG_ILIM_MASK,
105 reg);
106 if (ret != 0)
107 dev_err(wm831x->dev,
108 "Failed to set backup charger config: %d\n", ret);
109
110 wm831x_reg_lock(wm831x);
111}
112
113static int wm831x_backup_get_prop(struct power_supply *psy,
114 enum power_supply_property psp,
115 union power_supply_propval *val)
116{
117 struct wm831x_backup *devdata = dev_get_drvdata(psy->dev->parent);
118 struct wm831x *wm831x = devdata->wm831x;
119 int ret = 0;
120
121 ret = wm831x_reg_read(wm831x, WM831X_BACKUP_CHARGER_CONTROL);
122 if (ret < 0)
123 return ret;
124
125 switch (psp) {
126 case POWER_SUPPLY_PROP_STATUS:
127 if (ret & WM831X_BKUP_CHG_STS)
128 val->intval = POWER_SUPPLY_STATUS_CHARGING;
129 else
130 val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
131 break;
132
133 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
134 ret = wm831x_backup_read_voltage(wm831x, WM831X_AUX_BKUP_BATT,
135 val);
136 break;
137
138 case POWER_SUPPLY_PROP_PRESENT:
139 if (ret & WM831X_BKUP_CHG_STS)
140 val->intval = 1;
141 else
142 val->intval = 0;
143 break;
144
145 default:
146 ret = -EINVAL;
147 break;
148 }
149
150 return ret;
151}
152
153static enum power_supply_property wm831x_backup_props[] = {
154 POWER_SUPPLY_PROP_STATUS,
155 POWER_SUPPLY_PROP_VOLTAGE_NOW,
156 POWER_SUPPLY_PROP_PRESENT,
157};
158
159/*********************************************************************
160 * Initialisation
161 *********************************************************************/
162
163static __devinit int wm831x_backup_probe(struct platform_device *pdev)
164{
165 struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
166 struct wm831x_backup *devdata;
167 struct power_supply *backup;
168 int ret;
169
170 devdata = kzalloc(sizeof(struct wm831x_backup), GFP_KERNEL);
171 if (devdata == NULL)
172 return -ENOMEM;
173
174 devdata->wm831x = wm831x;
175 platform_set_drvdata(pdev, devdata);
176
177 backup = &devdata->backup;
178
179 /* We ignore configuration failures since we can still read
180 * back the status without enabling the charger (which may
181 * already be enabled anyway).
182 */
183 wm831x_config_backup(wm831x);
184
185 backup->name = "wm831x-backup";
186 backup->type = POWER_SUPPLY_TYPE_BATTERY;
187 backup->properties = wm831x_backup_props;
188 backup->num_properties = ARRAY_SIZE(wm831x_backup_props);
189 backup->get_property = wm831x_backup_get_prop;
190 ret = power_supply_register(&pdev->dev, backup);
191 if (ret)
192 goto err_kmalloc;
193
194 return ret;
195
196err_kmalloc:
197 kfree(devdata);
198 return ret;
199}
200
201static __devexit int wm831x_backup_remove(struct platform_device *pdev)
202{
203 struct wm831x_backup *devdata = platform_get_drvdata(pdev);
204
205 power_supply_unregister(&devdata->backup);
206 kfree(devdata);
207
208 return 0;
209}
210
211static struct platform_driver wm831x_backup_driver = {
212 .probe = wm831x_backup_probe,
213 .remove = __devexit_p(wm831x_backup_remove),
214 .driver = {
215 .name = "wm831x-backup",
216 },
217};
218
219static int __init wm831x_backup_init(void)
220{
221 return platform_driver_register(&wm831x_backup_driver);
222}
223module_init(wm831x_backup_init);
224
225static void __exit wm831x_backup_exit(void)
226{
227 platform_driver_unregister(&wm831x_backup_driver);
228}
229module_exit(wm831x_backup_exit);
230
231MODULE_DESCRIPTION("Backup battery charger driver for WM831x PMICs");
232MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
233MODULE_LICENSE("GPL");
234MODULE_ALIAS("platform:wm831x-backup");
diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c
index 2a4c8b0b829c..875c4d0f776b 100644
--- a/drivers/power/wm831x_power.c
+++ b/drivers/power/wm831x_power.c
@@ -12,6 +12,7 @@
12#include <linux/err.h> 12#include <linux/err.h>
13#include <linux/platform_device.h> 13#include <linux/platform_device.h>
14#include <linux/power_supply.h> 14#include <linux/power_supply.h>
15#include <linux/slab.h>
15 16
16#include <linux/mfd/wm831x/core.h> 17#include <linux/mfd/wm831x/core.h>
17#include <linux/mfd/wm831x/auxadc.h> 18#include <linux/mfd/wm831x/auxadc.h>
@@ -21,7 +22,6 @@
21struct wm831x_power { 22struct wm831x_power {
22 struct wm831x *wm831x; 23 struct wm831x *wm831x;
23 struct power_supply wall; 24 struct power_supply wall;
24 struct power_supply backup;
25 struct power_supply usb; 25 struct power_supply usb;
26 struct power_supply battery; 26 struct power_supply battery;
27}; 27};
@@ -454,125 +454,6 @@ static irqreturn_t wm831x_bat_irq(int irq, void *data)
454 454
455 455
456/********************************************************************* 456/*********************************************************************
457 * Backup supply properties
458 *********************************************************************/
459
460static void wm831x_config_backup(struct wm831x *wm831x)
461{
462 struct wm831x_pdata *wm831x_pdata = wm831x->dev->platform_data;
463 struct wm831x_backup_pdata *pdata;
464 int ret, reg;
465
466 if (!wm831x_pdata || !wm831x_pdata->backup) {
467 dev_warn(wm831x->dev,
468 "No backup battery charger configuration\n");
469 return;
470 }
471
472 pdata = wm831x_pdata->backup;
473
474 reg = 0;
475
476 if (pdata->charger_enable)
477 reg |= WM831X_BKUP_CHG_ENA | WM831X_BKUP_BATT_DET_ENA;
478 if (pdata->no_constant_voltage)
479 reg |= WM831X_BKUP_CHG_MODE;
480
481 switch (pdata->vlim) {
482 case 2500:
483 break;
484 case 3100:
485 reg |= WM831X_BKUP_CHG_VLIM;
486 break;
487 default:
488 dev_err(wm831x->dev, "Invalid backup voltage limit %dmV\n",
489 pdata->vlim);
490 }
491
492 switch (pdata->ilim) {
493 case 100:
494 break;
495 case 200:
496 reg |= 1;
497 break;
498 case 300:
499 reg |= 2;
500 break;
501 case 400:
502 reg |= 3;
503 break;
504 default:
505 dev_err(wm831x->dev, "Invalid backup current limit %duA\n",
506 pdata->ilim);
507 }
508
509 ret = wm831x_reg_unlock(wm831x);
510 if (ret != 0) {
511 dev_err(wm831x->dev, "Failed to unlock registers: %d\n", ret);
512 return;
513 }
514
515 ret = wm831x_set_bits(wm831x, WM831X_BACKUP_CHARGER_CONTROL,
516 WM831X_BKUP_CHG_ENA_MASK |
517 WM831X_BKUP_CHG_MODE_MASK |
518 WM831X_BKUP_BATT_DET_ENA_MASK |
519 WM831X_BKUP_CHG_VLIM_MASK |
520 WM831X_BKUP_CHG_ILIM_MASK,
521 reg);
522 if (ret != 0)
523 dev_err(wm831x->dev,
524 "Failed to set backup charger config: %d\n", ret);
525
526 wm831x_reg_lock(wm831x);
527}
528
529static int wm831x_backup_get_prop(struct power_supply *psy,
530 enum power_supply_property psp,
531 union power_supply_propval *val)
532{
533 struct wm831x_power *wm831x_power = dev_get_drvdata(psy->dev->parent);
534 struct wm831x *wm831x = wm831x_power->wm831x;
535 int ret = 0;
536
537 ret = wm831x_reg_read(wm831x, WM831X_BACKUP_CHARGER_CONTROL);
538 if (ret < 0)
539 return ret;
540
541 switch (psp) {
542 case POWER_SUPPLY_PROP_STATUS:
543 if (ret & WM831X_BKUP_CHG_STS)
544 val->intval = POWER_SUPPLY_STATUS_CHARGING;
545 else
546 val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
547 break;
548
549 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
550 ret = wm831x_power_read_voltage(wm831x, WM831X_AUX_BKUP_BATT,
551 val);
552 break;
553
554 case POWER_SUPPLY_PROP_PRESENT:
555 if (ret & WM831X_BKUP_CHG_STS)
556 val->intval = 1;
557 else
558 val->intval = 0;
559 break;
560
561 default:
562 ret = -EINVAL;
563 break;
564 }
565
566 return ret;
567}
568
569static enum power_supply_property wm831x_backup_props[] = {
570 POWER_SUPPLY_PROP_STATUS,
571 POWER_SUPPLY_PROP_VOLTAGE_NOW,
572 POWER_SUPPLY_PROP_PRESENT,
573};
574
575/*********************************************************************
576 * Initialisation 457 * Initialisation
577 *********************************************************************/ 458 *********************************************************************/
578 459
@@ -595,10 +476,7 @@ static irqreturn_t wm831x_pwr_src_irq(int irq, void *data)
595 476
596 dev_dbg(wm831x->dev, "Power source changed\n"); 477 dev_dbg(wm831x->dev, "Power source changed\n");
597 478
598 /* Just notify for everything - little harm in overnotifying. 479 /* Just notify for everything - little harm in overnotifying. */
599 * The backup battery is not a power source while the system
600 * is running so skip that.
601 */
602 power_supply_changed(&wm831x_power->battery); 480 power_supply_changed(&wm831x_power->battery);
603 power_supply_changed(&wm831x_power->usb); 481 power_supply_changed(&wm831x_power->usb);
604 power_supply_changed(&wm831x_power->wall); 482 power_supply_changed(&wm831x_power->wall);
@@ -613,7 +491,6 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev)
613 struct power_supply *usb; 491 struct power_supply *usb;
614 struct power_supply *battery; 492 struct power_supply *battery;
615 struct power_supply *wall; 493 struct power_supply *wall;
616 struct power_supply *backup;
617 int ret, irq, i; 494 int ret, irq, i;
618 495
619 power = kzalloc(sizeof(struct wm831x_power), GFP_KERNEL); 496 power = kzalloc(sizeof(struct wm831x_power), GFP_KERNEL);
@@ -626,13 +503,11 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev)
626 usb = &power->usb; 503 usb = &power->usb;
627 battery = &power->battery; 504 battery = &power->battery;
628 wall = &power->wall; 505 wall = &power->wall;
629 backup = &power->backup;
630 506
631 /* We ignore configuration failures since we can still read back 507 /* We ignore configuration failures since we can still read back
632 * the status without enabling either of the chargers. 508 * the status without enabling the charger.
633 */ 509 */
634 wm831x_config_battery(wm831x); 510 wm831x_config_battery(wm831x);
635 wm831x_config_backup(wm831x);
636 511
637 wall->name = "wm831x-wall"; 512 wall->name = "wm831x-wall";
638 wall->type = POWER_SUPPLY_TYPE_MAINS; 513 wall->type = POWER_SUPPLY_TYPE_MAINS;
@@ -661,15 +536,6 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev)
661 if (ret) 536 if (ret)
662 goto err_battery; 537 goto err_battery;
663 538
664 backup->name = "wm831x-backup";
665 backup->type = POWER_SUPPLY_TYPE_BATTERY;
666 backup->properties = wm831x_backup_props;
667 backup->num_properties = ARRAY_SIZE(wm831x_backup_props);
668 backup->get_property = wm831x_backup_get_prop;
669 ret = power_supply_register(&pdev->dev, backup);
670 if (ret)
671 goto err_usb;
672
673 irq = platform_get_irq_byname(pdev, "SYSLO"); 539 irq = platform_get_irq_byname(pdev, "SYSLO");
674 ret = wm831x_request_irq(wm831x, irq, wm831x_syslo_irq, 540 ret = wm831x_request_irq(wm831x, irq, wm831x_syslo_irq,
675 IRQF_TRIGGER_RISING, "SYSLO", 541 IRQF_TRIGGER_RISING, "SYSLO",
@@ -677,7 +543,7 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev)
677 if (ret != 0) { 543 if (ret != 0) {
678 dev_err(&pdev->dev, "Failed to request SYSLO IRQ %d: %d\n", 544 dev_err(&pdev->dev, "Failed to request SYSLO IRQ %d: %d\n",
679 irq, ret); 545 irq, ret);
680 goto err_backup; 546 goto err_usb;
681 } 547 }
682 548
683 irq = platform_get_irq_byname(pdev, "PWR SRC"); 549 irq = platform_get_irq_byname(pdev, "PWR SRC");
@@ -716,8 +582,6 @@ err_bat_irq:
716err_syslo: 582err_syslo:
717 irq = platform_get_irq_byname(pdev, "SYSLO"); 583 irq = platform_get_irq_byname(pdev, "SYSLO");
718 wm831x_free_irq(wm831x, irq, power); 584 wm831x_free_irq(wm831x, irq, power);
719err_backup:
720 power_supply_unregister(backup);
721err_usb: 585err_usb:
722 power_supply_unregister(usb); 586 power_supply_unregister(usb);
723err_battery: 587err_battery:
@@ -746,7 +610,6 @@ static __devexit int wm831x_power_remove(struct platform_device *pdev)
746 irq = platform_get_irq_byname(pdev, "SYSLO"); 610 irq = platform_get_irq_byname(pdev, "SYSLO");
747 wm831x_free_irq(wm831x, irq, wm831x_power); 611 wm831x_free_irq(wm831x, irq, wm831x_power);
748 612
749 power_supply_unregister(&wm831x_power->backup);
750 power_supply_unregister(&wm831x_power->battery); 613 power_supply_unregister(&wm831x_power->battery);
751 power_supply_unregister(&wm831x_power->wall); 614 power_supply_unregister(&wm831x_power->wall);
752 power_supply_unregister(&wm831x_power->usb); 615 power_supply_unregister(&wm831x_power->usb);
diff --git a/drivers/power/wm8350_power.c b/drivers/power/wm8350_power.c
index 28b0299c0043..0693902d6151 100644
--- a/drivers/power/wm8350_power.c
+++ b/drivers/power/wm8350_power.c
@@ -184,12 +184,13 @@ static ssize_t charger_state_show(struct device *dev,
184 184
185static DEVICE_ATTR(charger_state, 0444, charger_state_show, NULL); 185static DEVICE_ATTR(charger_state, 0444, charger_state_show, NULL);
186 186
187static void wm8350_charger_handler(struct wm8350 *wm8350, int irq, void *data) 187static irqreturn_t wm8350_charger_handler(int irq, void *data)
188{ 188{
189 struct wm8350 *wm8350 = data;
189 struct wm8350_power *power = &wm8350->power; 190 struct wm8350_power *power = &wm8350->power;
190 struct wm8350_charger_policy *policy = power->policy; 191 struct wm8350_charger_policy *policy = power->policy;
191 192
192 switch (irq) { 193 switch (irq - wm8350->irq_base) {
193 case WM8350_IRQ_CHG_BAT_FAIL: 194 case WM8350_IRQ_CHG_BAT_FAIL:
194 dev_err(wm8350->dev, "battery failed\n"); 195 dev_err(wm8350->dev, "battery failed\n");
195 break; 196 break;
@@ -238,6 +239,8 @@ static void wm8350_charger_handler(struct wm8350 *wm8350, int irq, void *data)
238 default: 239 default:
239 dev_err(wm8350->dev, "Unknown interrupt %d\n", irq); 240 dev_err(wm8350->dev, "Unknown interrupt %d\n", irq);
240 } 241 }
242
243 return IRQ_HANDLED;
241} 244}
242 245
243/********************************************************************* 246/*********************************************************************
@@ -387,74 +390,56 @@ static void wm8350_init_charger(struct wm8350 *wm8350)
387{ 390{
388 /* register our interest in charger events */ 391 /* register our interest in charger events */
389 wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT, 392 wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT,
390 wm8350_charger_handler, NULL); 393 wm8350_charger_handler, 0, "Battery hot", wm8350);
391 wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT);
392 wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD, 394 wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD,
393 wm8350_charger_handler, NULL); 395 wm8350_charger_handler, 0, "Battery cold", wm8350);
394 wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD);
395 wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL, 396 wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL,
396 wm8350_charger_handler, NULL); 397 wm8350_charger_handler, 0, "Battery fail", wm8350);
397 wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL);
398 wm8350_register_irq(wm8350, WM8350_IRQ_CHG_TO, 398 wm8350_register_irq(wm8350, WM8350_IRQ_CHG_TO,
399 wm8350_charger_handler, NULL); 399 wm8350_charger_handler, 0,
400 wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_TO); 400 "Charger timeout", wm8350);
401 wm8350_register_irq(wm8350, WM8350_IRQ_CHG_END, 401 wm8350_register_irq(wm8350, WM8350_IRQ_CHG_END,
402 wm8350_charger_handler, NULL); 402 wm8350_charger_handler, 0,
403 wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_END); 403 "Charge end", wm8350);
404 wm8350_register_irq(wm8350, WM8350_IRQ_CHG_START, 404 wm8350_register_irq(wm8350, WM8350_IRQ_CHG_START,
405 wm8350_charger_handler, NULL); 405 wm8350_charger_handler, 0,
406 wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_START); 406 "Charge start", wm8350);
407 wm8350_register_irq(wm8350, WM8350_IRQ_CHG_FAST_RDY, 407 wm8350_register_irq(wm8350, WM8350_IRQ_CHG_FAST_RDY,
408 wm8350_charger_handler, NULL); 408 wm8350_charger_handler, 0,
409 wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_FAST_RDY); 409 "Fast charge ready", wm8350);
410 wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9, 410 wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9,
411 wm8350_charger_handler, NULL); 411 wm8350_charger_handler, 0,
412 wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9); 412 "Battery <3.9V", wm8350);
413 wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1, 413 wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1,
414 wm8350_charger_handler, NULL); 414 wm8350_charger_handler, 0,
415 wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1); 415 "Battery <3.1V", wm8350);
416 wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85, 416 wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85,
417 wm8350_charger_handler, NULL); 417 wm8350_charger_handler, 0,
418 wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85); 418 "Battery <2.85V", wm8350);
419 419
420 /* and supply change events */ 420 /* and supply change events */
421 wm8350_register_irq(wm8350, WM8350_IRQ_EXT_USB_FB, 421 wm8350_register_irq(wm8350, WM8350_IRQ_EXT_USB_FB,
422 wm8350_charger_handler, NULL); 422 wm8350_charger_handler, 0, "USB", wm8350);
423 wm8350_unmask_irq(wm8350, WM8350_IRQ_EXT_USB_FB);
424 wm8350_register_irq(wm8350, WM8350_IRQ_EXT_WALL_FB, 423 wm8350_register_irq(wm8350, WM8350_IRQ_EXT_WALL_FB,
425 wm8350_charger_handler, NULL); 424 wm8350_charger_handler, 0, "Wall", wm8350);
426 wm8350_unmask_irq(wm8350, WM8350_IRQ_EXT_WALL_FB);
427 wm8350_register_irq(wm8350, WM8350_IRQ_EXT_BAT_FB, 425 wm8350_register_irq(wm8350, WM8350_IRQ_EXT_BAT_FB,
428 wm8350_charger_handler, NULL); 426 wm8350_charger_handler, 0, "Battery", wm8350);
429 wm8350_unmask_irq(wm8350, WM8350_IRQ_EXT_BAT_FB);
430} 427}
431 428
432static void free_charger_irq(struct wm8350 *wm8350) 429static void free_charger_irq(struct wm8350 *wm8350)
433{ 430{
434 wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT); 431 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT, wm8350);
435 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT); 432 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD, wm8350);
436 wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD); 433 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL, wm8350);
437 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD); 434 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_TO, wm8350);
438 wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL); 435 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_END, wm8350);
439 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL); 436 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_START, wm8350);
440 wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_TO); 437 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9, wm8350);
441 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_TO); 438 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1, wm8350);
442 wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_END); 439 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85, wm8350);
443 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_END); 440 wm8350_free_irq(wm8350, WM8350_IRQ_EXT_USB_FB, wm8350);
444 wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_START); 441 wm8350_free_irq(wm8350, WM8350_IRQ_EXT_WALL_FB, wm8350);
445 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_START); 442 wm8350_free_irq(wm8350, WM8350_IRQ_EXT_BAT_FB, wm8350);
446 wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9);
447 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9);
448 wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1);
449 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1);
450 wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85);
451 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85);
452 wm8350_mask_irq(wm8350, WM8350_IRQ_EXT_USB_FB);
453 wm8350_free_irq(wm8350, WM8350_IRQ_EXT_USB_FB);
454 wm8350_mask_irq(wm8350, WM8350_IRQ_EXT_WALL_FB);
455 wm8350_free_irq(wm8350, WM8350_IRQ_EXT_WALL_FB);
456 wm8350_mask_irq(wm8350, WM8350_IRQ_EXT_BAT_FB);
457 wm8350_free_irq(wm8350, WM8350_IRQ_EXT_BAT_FB);
458} 443}
459 444
460static __devinit int wm8350_power_probe(struct platform_device *pdev) 445static __devinit int wm8350_power_probe(struct platform_device *pdev)
diff --git a/drivers/power/wm97xx_battery.c b/drivers/power/wm97xx_battery.c
index f2bfd296dbae..94c70650aafc 100644
--- a/drivers/power/wm97xx_battery.c
+++ b/drivers/power/wm97xx_battery.c
@@ -23,10 +23,11 @@
23#include <linux/interrupt.h> 23#include <linux/interrupt.h>
24#include <linux/gpio.h> 24#include <linux/gpio.h>
25#include <linux/irq.h> 25#include <linux/irq.h>
26#include <linux/slab.h>
26 27
27static DEFINE_MUTEX(bat_lock); 28static DEFINE_MUTEX(bat_lock);
28static struct work_struct bat_work; 29static struct work_struct bat_work;
29struct mutex work_lock; 30static struct mutex work_lock;
30static int bat_status = POWER_SUPPLY_STATUS_UNKNOWN; 31static int bat_status = POWER_SUPPLY_STATUS_UNKNOWN;
31static struct wm97xx_batt_info *gpdata; 32static struct wm97xx_batt_info *gpdata;
32static enum power_supply_property *prop; 33static enum power_supply_property *prop;
@@ -157,7 +158,7 @@ static int wm97xx_bat_resume(struct device *dev)
157 return 0; 158 return 0;
158} 159}
159 160
160static struct dev_pm_ops wm97xx_bat_pm_ops = { 161static const struct dev_pm_ops wm97xx_bat_pm_ops = {
161 .suspend = wm97xx_bat_suspend, 162 .suspend = wm97xx_bat_suspend,
162 .resume = wm97xx_bat_resume, 163 .resume = wm97xx_bat_resume,
163}; 164};
@@ -175,8 +176,14 @@ static int __devinit wm97xx_bat_probe(struct platform_device *dev)
175 dev_err(&dev->dev, "Do not pass platform_data through " 176 dev_err(&dev->dev, "Do not pass platform_data through "
176 "wm97xx_bat_set_pdata!\n"); 177 "wm97xx_bat_set_pdata!\n");
177 return -EINVAL; 178 return -EINVAL;
178 } else 179 }
179 pdata = wmdata->batt_pdata; 180
181 if (!wmdata) {
182 dev_err(&dev->dev, "No platform data supplied\n");
183 return -EINVAL;
184 }
185
186 pdata = wmdata->batt_pdata;
180 187
181 if (dev->id != -1) 188 if (dev->id != -1)
182 return -EINVAL; 189 return -EINVAL;
@@ -197,7 +204,7 @@ static int __devinit wm97xx_bat_probe(struct platform_device *dev)
197 goto err2; 204 goto err2;
198 ret = request_irq(gpio_to_irq(pdata->charge_gpio), 205 ret = request_irq(gpio_to_irq(pdata->charge_gpio),
199 wm97xx_chrg_irq, IRQF_DISABLED, 206 wm97xx_chrg_irq, IRQF_DISABLED,
200 "AC Detect", 0); 207 "AC Detect", dev);
201 if (ret) 208 if (ret)
202 goto err2; 209 goto err2;
203 props++; /* POWER_SUPPLY_PROP_STATUS */ 210 props++; /* POWER_SUPPLY_PROP_STATUS */