diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-27 13:12:35 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-27 13:12:35 -0400 |
commit | ea0ca3a843babd50c22dfbb5cf2d9a14df821b2b (patch) | |
tree | 0d27fc6d7b9a0a2cdfe29833eb84ee07beac91ab /drivers/power | |
parent | 74e6392ca3fd445a775dd42b54d5e42cf1e706e6 (diff) | |
parent | 906649de0eacde7a643b5a0750de6207441ad54f (diff) |
Merge git://git.infradead.org/battery-2.6
* git://git.infradead.org/battery-2.6:
PXA: Use dev_pm_ops in z2_battery
ds2760_battery: Fix rated capacity of the hx4700 1800mAh battery
ds2760_battery: Fix indexing of the 4 active full EEPROM registers
power: Make test_power driver more dynamic.
bq27x00_battery: Name of cycle count property
max8903_charger: Add GENERIC_HARDIRQS as a dependency (fixes S390 build)
ARM: RX-51: Enable isp1704 power on/off
isp1704_charger: Allow board specific powering routine
gpio-charger: Add gpio_charger_resume
power_supply: Add driver for MAX8903 charger
Diffstat (limited to 'drivers/power')
-rw-r--r-- | drivers/power/Kconfig | 9 | ||||
-rw-r--r-- | drivers/power/Makefile | 1 | ||||
-rw-r--r-- | drivers/power/bq27x00_battery.c | 11 | ||||
-rw-r--r-- | drivers/power/ds2760_battery.c | 6 | ||||
-rw-r--r-- | drivers/power/gpio-charger.c | 15 | ||||
-rw-r--r-- | drivers/power/isp1704_charger.c | 22 | ||||
-rw-r--r-- | drivers/power/max8903_charger.c | 391 | ||||
-rw-r--r-- | drivers/power/test_power.c | 276 | ||||
-rw-r--r-- | drivers/power/z2_battery.c | 20 |
9 files changed, 729 insertions, 22 deletions
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index dc8c531ed276..e57b50b38565 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig | |||
@@ -210,6 +210,15 @@ config CHARGER_ISP1704 | |||
210 | Say Y to enable support for USB Charger Detection with | 210 | Say Y to enable support for USB Charger Detection with |
211 | ISP1707/ISP1704 USB transceivers. | 211 | ISP1707/ISP1704 USB transceivers. |
212 | 212 | ||
213 | config CHARGER_MAX8903 | ||
214 | tristate "MAX8903 Battery DC-DC Charger for USB and Adapter Power" | ||
215 | depends on GENERIC_HARDIRQS | ||
216 | help | ||
217 | Say Y to enable support for the MAX8903 DC-DC charger and sysfs. | ||
218 | The driver supports controlling charger-enable and current-limit | ||
219 | pins based on the status of charger connections with interrupt | ||
220 | handlers. | ||
221 | |||
213 | config CHARGER_TWL4030 | 222 | config CHARGER_TWL4030 |
214 | tristate "OMAP TWL4030 BCI charger driver" | 223 | tristate "OMAP TWL4030 BCI charger driver" |
215 | depends on TWL4030_CORE | 224 | depends on TWL4030_CORE |
diff --git a/drivers/power/Makefile b/drivers/power/Makefile index 8224990b933d..009a90fa8ac9 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile | |||
@@ -33,5 +33,6 @@ obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o | |||
33 | obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o | 33 | obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o |
34 | obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o | 34 | obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o |
35 | obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o | 35 | obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o |
36 | obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o | ||
36 | obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o | 37 | obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o |
37 | obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o | 38 | obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o |
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c index 59e68dbd028b..bb16f5b7e167 100644 --- a/drivers/power/bq27x00_battery.c +++ b/drivers/power/bq27x00_battery.c | |||
@@ -4,6 +4,7 @@ | |||
4 | * Copyright (C) 2008 Rodolfo Giometti <giometti@linux.it> | 4 | * Copyright (C) 2008 Rodolfo Giometti <giometti@linux.it> |
5 | * Copyright (C) 2008 Eurotech S.p.A. <info@eurotech.it> | 5 | * Copyright (C) 2008 Eurotech S.p.A. <info@eurotech.it> |
6 | * Copyright (C) 2010-2011 Lars-Peter Clausen <lars@metafoo.de> | 6 | * Copyright (C) 2010-2011 Lars-Peter Clausen <lars@metafoo.de> |
7 | * Copyright (C) 2011 Pali Rohár <pali.rohar@gmail.com> | ||
7 | * | 8 | * |
8 | * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc. | 9 | * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc. |
9 | * | 10 | * |
@@ -76,7 +77,7 @@ struct bq27x00_reg_cache { | |||
76 | int time_to_empty_avg; | 77 | int time_to_empty_avg; |
77 | int time_to_full; | 78 | int time_to_full; |
78 | int charge_full; | 79 | int charge_full; |
79 | int charge_counter; | 80 | int cycle_count; |
80 | int capacity; | 81 | int capacity; |
81 | int flags; | 82 | int flags; |
82 | 83 | ||
@@ -115,7 +116,7 @@ static enum power_supply_property bq27x00_battery_props[] = { | |||
115 | POWER_SUPPLY_PROP_CHARGE_FULL, | 116 | POWER_SUPPLY_PROP_CHARGE_FULL, |
116 | POWER_SUPPLY_PROP_CHARGE_NOW, | 117 | POWER_SUPPLY_PROP_CHARGE_NOW, |
117 | POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, | 118 | POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, |
118 | POWER_SUPPLY_PROP_CHARGE_COUNTER, | 119 | POWER_SUPPLY_PROP_CYCLE_COUNT, |
119 | POWER_SUPPLY_PROP_ENERGY_NOW, | 120 | POWER_SUPPLY_PROP_ENERGY_NOW, |
120 | }; | 121 | }; |
121 | 122 | ||
@@ -267,7 +268,7 @@ static void bq27x00_update(struct bq27x00_device_info *di) | |||
267 | cache.time_to_empty_avg = bq27x00_battery_read_time(di, BQ27x00_REG_TTECP); | 268 | cache.time_to_empty_avg = bq27x00_battery_read_time(di, BQ27x00_REG_TTECP); |
268 | cache.time_to_full = bq27x00_battery_read_time(di, BQ27x00_REG_TTF); | 269 | cache.time_to_full = bq27x00_battery_read_time(di, BQ27x00_REG_TTF); |
269 | cache.charge_full = bq27x00_battery_read_lmd(di); | 270 | cache.charge_full = bq27x00_battery_read_lmd(di); |
270 | cache.charge_counter = bq27x00_battery_read_cyct(di); | 271 | cache.cycle_count = bq27x00_battery_read_cyct(di); |
271 | 272 | ||
272 | if (!is_bq27500) | 273 | if (!is_bq27500) |
273 | cache.current_now = bq27x00_read(di, BQ27x00_REG_AI, false); | 274 | cache.current_now = bq27x00_read(di, BQ27x00_REG_AI, false); |
@@ -496,8 +497,8 @@ static int bq27x00_battery_get_property(struct power_supply *psy, | |||
496 | case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: | 497 | case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: |
497 | ret = bq27x00_simple_value(di->charge_design_full, val); | 498 | ret = bq27x00_simple_value(di->charge_design_full, val); |
498 | break; | 499 | break; |
499 | case POWER_SUPPLY_PROP_CHARGE_COUNTER: | 500 | case POWER_SUPPLY_PROP_CYCLE_COUNT: |
500 | ret = bq27x00_simple_value(di->cache.charge_counter, val); | 501 | ret = bq27x00_simple_value(di->cache.cycle_count, val); |
501 | break; | 502 | break; |
502 | case POWER_SUPPLY_PROP_ENERGY_NOW: | 503 | case POWER_SUPPLY_PROP_ENERGY_NOW: |
503 | ret = bq27x00_battery_energy(di, val); | 504 | ret = bq27x00_battery_energy(di, val); |
diff --git a/drivers/power/ds2760_battery.c b/drivers/power/ds2760_battery.c index e534290f3256..f2c9cc33c0f9 100644 --- a/drivers/power/ds2760_battery.c +++ b/drivers/power/ds2760_battery.c | |||
@@ -86,7 +86,11 @@ static int rated_capacities[] = { | |||
86 | 920, /* NEC */ | 86 | 920, /* NEC */ |
87 | 1440, /* Samsung */ | 87 | 1440, /* Samsung */ |
88 | 1440, /* BYD */ | 88 | 1440, /* BYD */ |
89 | #ifdef CONFIG_MACH_H4700 | ||
90 | 1800, /* HP iPAQ hx4700 3.7V 1800mAh (359113-001) */ | ||
91 | #else | ||
89 | 1440, /* Lishen */ | 92 | 1440, /* Lishen */ |
93 | #endif | ||
90 | 1440, /* NEC */ | 94 | 1440, /* NEC */ |
91 | 2880, /* Samsung */ | 95 | 2880, /* Samsung */ |
92 | 2880, /* BYD */ | 96 | 2880, /* BYD */ |
@@ -186,7 +190,7 @@ static int ds2760_battery_read_status(struct ds2760_device_info *di) | |||
186 | 190 | ||
187 | scale[0] = di->full_active_uAh; | 191 | scale[0] = di->full_active_uAh; |
188 | for (i = 1; i < 5; i++) | 192 | for (i = 1; i < 5; i++) |
189 | scale[i] = scale[i - 1] + di->raw[DS2760_ACTIVE_FULL + 2 + i]; | 193 | scale[i] = scale[i - 1] + di->raw[DS2760_ACTIVE_FULL + 1 + i]; |
190 | 194 | ||
191 | di->full_active_uAh = battery_interpolate(scale, di->temp_C / 10); | 195 | di->full_active_uAh = battery_interpolate(scale, di->temp_C / 10); |
192 | di->full_active_uAh *= 1000; /* convert to µAh */ | 196 | di->full_active_uAh *= 1000; /* convert to µAh */ |
diff --git a/drivers/power/gpio-charger.c b/drivers/power/gpio-charger.c index 25b88ac1d44c..718f2c537827 100644 --- a/drivers/power/gpio-charger.c +++ b/drivers/power/gpio-charger.c | |||
@@ -161,12 +161,27 @@ static int __devexit gpio_charger_remove(struct platform_device *pdev) | |||
161 | return 0; | 161 | return 0; |
162 | } | 162 | } |
163 | 163 | ||
164 | #ifdef CONFIG_PM_SLEEP | ||
165 | static int gpio_charger_resume(struct device *dev) | ||
166 | { | ||
167 | struct platform_device *pdev = to_platform_device(dev); | ||
168 | struct gpio_charger *gpio_charger = platform_get_drvdata(pdev); | ||
169 | |||
170 | power_supply_changed(&gpio_charger->charger); | ||
171 | |||
172 | return 0; | ||
173 | } | ||
174 | #endif | ||
175 | |||
176 | static SIMPLE_DEV_PM_OPS(gpio_charger_pm_ops, NULL, gpio_charger_resume); | ||
177 | |||
164 | static struct platform_driver gpio_charger_driver = { | 178 | static struct platform_driver gpio_charger_driver = { |
165 | .probe = gpio_charger_probe, | 179 | .probe = gpio_charger_probe, |
166 | .remove = __devexit_p(gpio_charger_remove), | 180 | .remove = __devexit_p(gpio_charger_remove), |
167 | .driver = { | 181 | .driver = { |
168 | .name = "gpio-charger", | 182 | .name = "gpio-charger", |
169 | .owner = THIS_MODULE, | 183 | .owner = THIS_MODULE, |
184 | .pm = &gpio_charger_pm_ops, | ||
170 | }, | 185 | }, |
171 | }; | 186 | }; |
172 | 187 | ||
diff --git a/drivers/power/isp1704_charger.c b/drivers/power/isp1704_charger.c index 2ad9b14a5ce3..f6d72b402a8e 100644 --- a/drivers/power/isp1704_charger.c +++ b/drivers/power/isp1704_charger.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/usb/ulpi.h> | 33 | #include <linux/usb/ulpi.h> |
34 | #include <linux/usb/ch9.h> | 34 | #include <linux/usb/ch9.h> |
35 | #include <linux/usb/gadget.h> | 35 | #include <linux/usb/gadget.h> |
36 | #include <linux/power/isp1704_charger.h> | ||
36 | 37 | ||
37 | /* Vendor specific Power Control register */ | 38 | /* Vendor specific Power Control register */ |
38 | #define ISP1704_PWR_CTRL 0x3d | 39 | #define ISP1704_PWR_CTRL 0x3d |
@@ -71,6 +72,18 @@ struct isp1704_charger { | |||
71 | }; | 72 | }; |
72 | 73 | ||
73 | /* | 74 | /* |
75 | * Disable/enable the power from the isp1704 if a function for it | ||
76 | * has been provided with platform data. | ||
77 | */ | ||
78 | static void isp1704_charger_set_power(struct isp1704_charger *isp, bool on) | ||
79 | { | ||
80 | struct isp1704_charger_data *board = isp->dev->platform_data; | ||
81 | |||
82 | if (board->set_power) | ||
83 | board->set_power(on); | ||
84 | } | ||
85 | |||
86 | /* | ||
74 | * Determine is the charging port DCP (dedicated charger) or CDP (Host/HUB | 87 | * Determine is the charging port DCP (dedicated charger) or CDP (Host/HUB |
75 | * chargers). | 88 | * chargers). |
76 | * | 89 | * |
@@ -222,6 +235,9 @@ static void isp1704_charger_work(struct work_struct *data) | |||
222 | 235 | ||
223 | mutex_lock(&lock); | 236 | mutex_lock(&lock); |
224 | 237 | ||
238 | if (event != USB_EVENT_NONE) | ||
239 | isp1704_charger_set_power(isp, 1); | ||
240 | |||
225 | switch (event) { | 241 | switch (event) { |
226 | case USB_EVENT_VBUS: | 242 | case USB_EVENT_VBUS: |
227 | isp->online = true; | 243 | isp->online = true; |
@@ -269,6 +285,8 @@ static void isp1704_charger_work(struct work_struct *data) | |||
269 | */ | 285 | */ |
270 | if (isp->otg->gadget) | 286 | if (isp->otg->gadget) |
271 | usb_gadget_disconnect(isp->otg->gadget); | 287 | usb_gadget_disconnect(isp->otg->gadget); |
288 | |||
289 | isp1704_charger_set_power(isp, 0); | ||
272 | break; | 290 | break; |
273 | case USB_EVENT_ENUMERATED: | 291 | case USB_EVENT_ENUMERATED: |
274 | if (isp->present) | 292 | if (isp->present) |
@@ -394,6 +412,8 @@ static int __devinit isp1704_charger_probe(struct platform_device *pdev) | |||
394 | isp->dev = &pdev->dev; | 412 | isp->dev = &pdev->dev; |
395 | platform_set_drvdata(pdev, isp); | 413 | platform_set_drvdata(pdev, isp); |
396 | 414 | ||
415 | isp1704_charger_set_power(isp, 1); | ||
416 | |||
397 | ret = isp1704_test_ulpi(isp); | 417 | ret = isp1704_test_ulpi(isp); |
398 | if (ret < 0) | 418 | if (ret < 0) |
399 | goto fail1; | 419 | goto fail1; |
@@ -434,6 +454,7 @@ static int __devinit isp1704_charger_probe(struct platform_device *pdev) | |||
434 | 454 | ||
435 | /* Detect charger if VBUS is valid (the cable was already plugged). */ | 455 | /* Detect charger if VBUS is valid (the cable was already plugged). */ |
436 | ret = otg_io_read(isp->otg, ULPI_USB_INT_STS); | 456 | ret = otg_io_read(isp->otg, ULPI_USB_INT_STS); |
457 | isp1704_charger_set_power(isp, 0); | ||
437 | if ((ret & ULPI_INT_VBUS_VALID) && !isp->otg->default_a) { | 458 | if ((ret & ULPI_INT_VBUS_VALID) && !isp->otg->default_a) { |
438 | isp->event = USB_EVENT_VBUS; | 459 | isp->event = USB_EVENT_VBUS; |
439 | schedule_work(&isp->work); | 460 | schedule_work(&isp->work); |
@@ -459,6 +480,7 @@ static int __devexit isp1704_charger_remove(struct platform_device *pdev) | |||
459 | otg_unregister_notifier(isp->otg, &isp->nb); | 480 | otg_unregister_notifier(isp->otg, &isp->nb); |
460 | power_supply_unregister(&isp->psy); | 481 | power_supply_unregister(&isp->psy); |
461 | otg_put_transceiver(isp->otg); | 482 | otg_put_transceiver(isp->otg); |
483 | isp1704_charger_set_power(isp, 0); | ||
462 | kfree(isp); | 484 | kfree(isp); |
463 | 485 | ||
464 | return 0; | 486 | return 0; |
diff --git a/drivers/power/max8903_charger.c b/drivers/power/max8903_charger.c new file mode 100644 index 000000000000..33ff0e37809e --- /dev/null +++ b/drivers/power/max8903_charger.c | |||
@@ -0,0 +1,391 @@ | |||
1 | /* | ||
2 | * max8903_charger.c - Maxim 8903 USB/Adapter Charger Driver | ||
3 | * | ||
4 | * Copyright (C) 2011 Samsung Electronics | ||
5 | * MyungJoo Ham <myungjoo.ham@samsung.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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <linux/gpio.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/slab.h> | ||
26 | #include <linux/power_supply.h> | ||
27 | #include <linux/platform_device.h> | ||
28 | #include <linux/power/max8903_charger.h> | ||
29 | |||
30 | struct max8903_data { | ||
31 | struct max8903_pdata *pdata; | ||
32 | struct device *dev; | ||
33 | struct power_supply psy; | ||
34 | bool fault; | ||
35 | bool usb_in; | ||
36 | bool ta_in; | ||
37 | }; | ||
38 | |||
39 | static enum power_supply_property max8903_charger_props[] = { | ||
40 | POWER_SUPPLY_PROP_STATUS, /* Charger status output */ | ||
41 | POWER_SUPPLY_PROP_ONLINE, /* External power source */ | ||
42 | POWER_SUPPLY_PROP_HEALTH, /* Fault or OK */ | ||
43 | }; | ||
44 | |||
45 | static int max8903_get_property(struct power_supply *psy, | ||
46 | enum power_supply_property psp, | ||
47 | union power_supply_propval *val) | ||
48 | { | ||
49 | struct max8903_data *data = container_of(psy, | ||
50 | struct max8903_data, psy); | ||
51 | |||
52 | switch (psp) { | ||
53 | case POWER_SUPPLY_PROP_STATUS: | ||
54 | val->intval = POWER_SUPPLY_STATUS_UNKNOWN; | ||
55 | if (data->pdata->chg) { | ||
56 | if (gpio_get_value(data->pdata->chg) == 0) | ||
57 | val->intval = POWER_SUPPLY_STATUS_CHARGING; | ||
58 | else if (data->usb_in || data->ta_in) | ||
59 | val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
60 | else | ||
61 | val->intval = POWER_SUPPLY_STATUS_DISCHARGING; | ||
62 | } | ||
63 | break; | ||
64 | case POWER_SUPPLY_PROP_ONLINE: | ||
65 | val->intval = 0; | ||
66 | if (data->usb_in || data->ta_in) | ||
67 | val->intval = 1; | ||
68 | break; | ||
69 | case POWER_SUPPLY_PROP_HEALTH: | ||
70 | val->intval = POWER_SUPPLY_HEALTH_GOOD; | ||
71 | if (data->fault) | ||
72 | val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; | ||
73 | break; | ||
74 | default: | ||
75 | return -EINVAL; | ||
76 | } | ||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | static irqreturn_t max8903_dcin(int irq, void *_data) | ||
81 | { | ||
82 | struct max8903_data *data = _data; | ||
83 | struct max8903_pdata *pdata = data->pdata; | ||
84 | bool ta_in; | ||
85 | enum power_supply_type old_type; | ||
86 | |||
87 | ta_in = gpio_get_value(pdata->dok) ? false : true; | ||
88 | |||
89 | if (ta_in == data->ta_in) | ||
90 | return IRQ_HANDLED; | ||
91 | |||
92 | data->ta_in = ta_in; | ||
93 | |||
94 | /* Set Current-Limit-Mode 1:DC 0:USB */ | ||
95 | if (pdata->dcm) | ||
96 | gpio_set_value(pdata->dcm, ta_in ? 1 : 0); | ||
97 | |||
98 | /* Charger Enable / Disable (cen is negated) */ | ||
99 | if (pdata->cen) | ||
100 | gpio_set_value(pdata->cen, ta_in ? 0 : | ||
101 | (data->usb_in ? 0 : 1)); | ||
102 | |||
103 | dev_dbg(data->dev, "TA(DC-IN) Charger %s.\n", ta_in ? | ||
104 | "Connected" : "Disconnected"); | ||
105 | |||
106 | old_type = data->psy.type; | ||
107 | |||
108 | if (data->ta_in) | ||
109 | data->psy.type = POWER_SUPPLY_TYPE_MAINS; | ||
110 | else if (data->usb_in) | ||
111 | data->psy.type = POWER_SUPPLY_TYPE_USB; | ||
112 | else | ||
113 | data->psy.type = POWER_SUPPLY_TYPE_BATTERY; | ||
114 | |||
115 | if (old_type != data->psy.type) | ||
116 | power_supply_changed(&data->psy); | ||
117 | |||
118 | return IRQ_HANDLED; | ||
119 | } | ||
120 | |||
121 | static irqreturn_t max8903_usbin(int irq, void *_data) | ||
122 | { | ||
123 | struct max8903_data *data = _data; | ||
124 | struct max8903_pdata *pdata = data->pdata; | ||
125 | bool usb_in; | ||
126 | enum power_supply_type old_type; | ||
127 | |||
128 | usb_in = gpio_get_value(pdata->uok) ? false : true; | ||
129 | |||
130 | if (usb_in == data->usb_in) | ||
131 | return IRQ_HANDLED; | ||
132 | |||
133 | data->usb_in = usb_in; | ||
134 | |||
135 | /* Do not touch Current-Limit-Mode */ | ||
136 | |||
137 | /* Charger Enable / Disable (cen is negated) */ | ||
138 | if (pdata->cen) | ||
139 | gpio_set_value(pdata->cen, usb_in ? 0 : | ||
140 | (data->ta_in ? 0 : 1)); | ||
141 | |||
142 | dev_dbg(data->dev, "USB Charger %s.\n", usb_in ? | ||
143 | "Connected" : "Disconnected"); | ||
144 | |||
145 | old_type = data->psy.type; | ||
146 | |||
147 | if (data->ta_in) | ||
148 | data->psy.type = POWER_SUPPLY_TYPE_MAINS; | ||
149 | else if (data->usb_in) | ||
150 | data->psy.type = POWER_SUPPLY_TYPE_USB; | ||
151 | else | ||
152 | data->psy.type = POWER_SUPPLY_TYPE_BATTERY; | ||
153 | |||
154 | if (old_type != data->psy.type) | ||
155 | power_supply_changed(&data->psy); | ||
156 | |||
157 | return IRQ_HANDLED; | ||
158 | } | ||
159 | |||
160 | static irqreturn_t max8903_fault(int irq, void *_data) | ||
161 | { | ||
162 | struct max8903_data *data = _data; | ||
163 | struct max8903_pdata *pdata = data->pdata; | ||
164 | bool fault; | ||
165 | |||
166 | fault = gpio_get_value(pdata->flt) ? false : true; | ||
167 | |||
168 | if (fault == data->fault) | ||
169 | return IRQ_HANDLED; | ||
170 | |||
171 | data->fault = fault; | ||
172 | |||
173 | if (fault) | ||
174 | dev_err(data->dev, "Charger suffers a fault and stops.\n"); | ||
175 | else | ||
176 | dev_err(data->dev, "Charger recovered from a fault.\n"); | ||
177 | |||
178 | return IRQ_HANDLED; | ||
179 | } | ||
180 | |||
181 | static __devinit int max8903_probe(struct platform_device *pdev) | ||
182 | { | ||
183 | struct max8903_data *data; | ||
184 | struct device *dev = &pdev->dev; | ||
185 | struct max8903_pdata *pdata = pdev->dev.platform_data; | ||
186 | int ret = 0; | ||
187 | int gpio; | ||
188 | int ta_in = 0; | ||
189 | int usb_in = 0; | ||
190 | |||
191 | data = kzalloc(sizeof(struct max8903_data), GFP_KERNEL); | ||
192 | if (data == NULL) { | ||
193 | dev_err(dev, "Cannot allocate memory.\n"); | ||
194 | return -ENOMEM; | ||
195 | } | ||
196 | data->pdata = pdata; | ||
197 | data->dev = dev; | ||
198 | platform_set_drvdata(pdev, data); | ||
199 | |||
200 | if (pdata->dc_valid == false && pdata->usb_valid == false) { | ||
201 | dev_err(dev, "No valid power sources.\n"); | ||
202 | ret = -EINVAL; | ||
203 | goto err; | ||
204 | } | ||
205 | |||
206 | if (pdata->dc_valid) { | ||
207 | if (pdata->dok && gpio_is_valid(pdata->dok) && | ||
208 | pdata->dcm && gpio_is_valid(pdata->dcm)) { | ||
209 | gpio = pdata->dok; /* PULL_UPed Interrupt */ | ||
210 | ta_in = gpio_get_value(gpio) ? 0 : 1; | ||
211 | |||
212 | gpio = pdata->dcm; /* Output */ | ||
213 | gpio_set_value(gpio, ta_in); | ||
214 | } else { | ||
215 | dev_err(dev, "When DC is wired, DOK and DCM should" | ||
216 | " be wired as well.\n"); | ||
217 | ret = -EINVAL; | ||
218 | goto err; | ||
219 | } | ||
220 | } else { | ||
221 | if (pdata->dcm) { | ||
222 | if (gpio_is_valid(pdata->dcm)) | ||
223 | gpio_set_value(pdata->dcm, 0); | ||
224 | else { | ||
225 | dev_err(dev, "Invalid pin: dcm.\n"); | ||
226 | ret = -EINVAL; | ||
227 | goto err; | ||
228 | } | ||
229 | } | ||
230 | } | ||
231 | |||
232 | if (pdata->usb_valid) { | ||
233 | if (pdata->uok && gpio_is_valid(pdata->uok)) { | ||
234 | gpio = pdata->uok; | ||
235 | usb_in = gpio_get_value(gpio) ? 0 : 1; | ||
236 | } else { | ||
237 | dev_err(dev, "When USB is wired, UOK should be wired." | ||
238 | "as well.\n"); | ||
239 | ret = -EINVAL; | ||
240 | goto err; | ||
241 | } | ||
242 | } | ||
243 | |||
244 | if (pdata->cen) { | ||
245 | if (gpio_is_valid(pdata->cen)) { | ||
246 | gpio_set_value(pdata->cen, (ta_in || usb_in) ? 0 : 1); | ||
247 | } else { | ||
248 | dev_err(dev, "Invalid pin: cen.\n"); | ||
249 | ret = -EINVAL; | ||
250 | goto err; | ||
251 | } | ||
252 | } | ||
253 | |||
254 | if (pdata->chg) { | ||
255 | if (!gpio_is_valid(pdata->chg)) { | ||
256 | dev_err(dev, "Invalid pin: chg.\n"); | ||
257 | ret = -EINVAL; | ||
258 | goto err; | ||
259 | } | ||
260 | } | ||
261 | |||
262 | if (pdata->flt) { | ||
263 | if (!gpio_is_valid(pdata->flt)) { | ||
264 | dev_err(dev, "Invalid pin: flt.\n"); | ||
265 | ret = -EINVAL; | ||
266 | goto err; | ||
267 | } | ||
268 | } | ||
269 | |||
270 | if (pdata->usus) { | ||
271 | if (!gpio_is_valid(pdata->usus)) { | ||
272 | dev_err(dev, "Invalid pin: usus.\n"); | ||
273 | ret = -EINVAL; | ||
274 | goto err; | ||
275 | } | ||
276 | } | ||
277 | |||
278 | data->fault = false; | ||
279 | data->ta_in = ta_in; | ||
280 | data->usb_in = usb_in; | ||
281 | |||
282 | data->psy.name = "max8903_charger"; | ||
283 | data->psy.type = (ta_in) ? POWER_SUPPLY_TYPE_MAINS : | ||
284 | ((usb_in) ? POWER_SUPPLY_TYPE_USB : | ||
285 | POWER_SUPPLY_TYPE_BATTERY); | ||
286 | data->psy.get_property = max8903_get_property; | ||
287 | data->psy.properties = max8903_charger_props; | ||
288 | data->psy.num_properties = ARRAY_SIZE(max8903_charger_props); | ||
289 | |||
290 | ret = power_supply_register(dev, &data->psy); | ||
291 | if (ret) { | ||
292 | dev_err(dev, "failed: power supply register.\n"); | ||
293 | goto err; | ||
294 | } | ||
295 | |||
296 | if (pdata->dc_valid) { | ||
297 | ret = request_threaded_irq(gpio_to_irq(pdata->dok), | ||
298 | NULL, max8903_dcin, | ||
299 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, | ||
300 | "MAX8903 DC IN", data); | ||
301 | if (ret) { | ||
302 | dev_err(dev, "Cannot request irq %d for DC (%d)\n", | ||
303 | gpio_to_irq(pdata->dok), ret); | ||
304 | goto err_psy; | ||
305 | } | ||
306 | } | ||
307 | |||
308 | if (pdata->usb_valid) { | ||
309 | ret = request_threaded_irq(gpio_to_irq(pdata->uok), | ||
310 | NULL, max8903_usbin, | ||
311 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, | ||
312 | "MAX8903 USB IN", data); | ||
313 | if (ret) { | ||
314 | dev_err(dev, "Cannot request irq %d for USB (%d)\n", | ||
315 | gpio_to_irq(pdata->uok), ret); | ||
316 | goto err_dc_irq; | ||
317 | } | ||
318 | } | ||
319 | |||
320 | if (pdata->flt) { | ||
321 | ret = request_threaded_irq(gpio_to_irq(pdata->flt), | ||
322 | NULL, max8903_fault, | ||
323 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, | ||
324 | "MAX8903 Fault", data); | ||
325 | if (ret) { | ||
326 | dev_err(dev, "Cannot request irq %d for Fault (%d)\n", | ||
327 | gpio_to_irq(pdata->flt), ret); | ||
328 | goto err_usb_irq; | ||
329 | } | ||
330 | } | ||
331 | |||
332 | return 0; | ||
333 | |||
334 | err_usb_irq: | ||
335 | if (pdata->usb_valid) | ||
336 | free_irq(gpio_to_irq(pdata->uok), data); | ||
337 | err_dc_irq: | ||
338 | if (pdata->dc_valid) | ||
339 | free_irq(gpio_to_irq(pdata->dok), data); | ||
340 | err_psy: | ||
341 | power_supply_unregister(&data->psy); | ||
342 | err: | ||
343 | kfree(data); | ||
344 | return ret; | ||
345 | } | ||
346 | |||
347 | static __devexit int max8903_remove(struct platform_device *pdev) | ||
348 | { | ||
349 | struct max8903_data *data = platform_get_drvdata(pdev); | ||
350 | |||
351 | if (data) { | ||
352 | struct max8903_pdata *pdata = data->pdata; | ||
353 | |||
354 | if (pdata->flt) | ||
355 | free_irq(gpio_to_irq(pdata->flt), data); | ||
356 | if (pdata->usb_valid) | ||
357 | free_irq(gpio_to_irq(pdata->uok), data); | ||
358 | if (pdata->dc_valid) | ||
359 | free_irq(gpio_to_irq(pdata->dok), data); | ||
360 | power_supply_unregister(&data->psy); | ||
361 | kfree(data); | ||
362 | } | ||
363 | |||
364 | return 0; | ||
365 | } | ||
366 | |||
367 | static struct platform_driver max8903_driver = { | ||
368 | .probe = max8903_probe, | ||
369 | .remove = __devexit_p(max8903_remove), | ||
370 | .driver = { | ||
371 | .name = "max8903-charger", | ||
372 | .owner = THIS_MODULE, | ||
373 | }, | ||
374 | }; | ||
375 | |||
376 | static int __init max8903_init(void) | ||
377 | { | ||
378 | return platform_driver_register(&max8903_driver); | ||
379 | } | ||
380 | module_init(max8903_init); | ||
381 | |||
382 | static void __exit max8903_exit(void) | ||
383 | { | ||
384 | platform_driver_unregister(&max8903_driver); | ||
385 | } | ||
386 | module_exit(max8903_exit); | ||
387 | |||
388 | MODULE_LICENSE("GPL"); | ||
389 | MODULE_DESCRIPTION("MAX8903 Charger Driver"); | ||
390 | MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>"); | ||
391 | MODULE_ALIAS("max8903-charger"); | ||
diff --git a/drivers/power/test_power.c b/drivers/power/test_power.c index 0cd9f67d33e5..b527c93bf2f3 100644 --- a/drivers/power/test_power.c +++ b/drivers/power/test_power.c | |||
@@ -3,6 +3,12 @@ | |||
3 | * | 3 | * |
4 | * Copyright 2010 Anton Vorontsov <cbouatmailru@gmail.com> | 4 | * Copyright 2010 Anton Vorontsov <cbouatmailru@gmail.com> |
5 | * | 5 | * |
6 | * Dynamic module parameter code from the Virtual Battery Driver | ||
7 | * Copyright (C) 2008 Pylone, Inc. | ||
8 | * By: Masashi YOKOTA <yokota@pylone.jp> | ||
9 | * Originally found here: | ||
10 | * http://downloads.pylone.jp/src/virtual_battery/virtual_battery-0.0.1.tar.bz2 | ||
11 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | 12 | * 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 | 13 | * it under the terms of the GNU General Public License version 2 as |
8 | * published by the Free Software Foundation. | 14 | * published by the Free Software Foundation. |
@@ -15,8 +21,12 @@ | |||
15 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
16 | #include <linux/vermagic.h> | 22 | #include <linux/vermagic.h> |
17 | 23 | ||
18 | static int test_power_ac_online = 1; | 24 | static int ac_online = 1; |
19 | static int test_power_battery_status = POWER_SUPPLY_STATUS_CHARGING; | 25 | static int battery_status = POWER_SUPPLY_STATUS_DISCHARGING; |
26 | static int battery_health = POWER_SUPPLY_HEALTH_GOOD; | ||
27 | static int battery_present = 1; /* true */ | ||
28 | static int battery_technology = POWER_SUPPLY_TECHNOLOGY_LION; | ||
29 | static int battery_capacity = 50; | ||
20 | 30 | ||
21 | static int test_power_get_ac_property(struct power_supply *psy, | 31 | static int test_power_get_ac_property(struct power_supply *psy, |
22 | enum power_supply_property psp, | 32 | enum power_supply_property psp, |
@@ -24,7 +34,7 @@ static int test_power_get_ac_property(struct power_supply *psy, | |||
24 | { | 34 | { |
25 | switch (psp) { | 35 | switch (psp) { |
26 | case POWER_SUPPLY_PROP_ONLINE: | 36 | case POWER_SUPPLY_PROP_ONLINE: |
27 | val->intval = test_power_ac_online; | 37 | val->intval = ac_online; |
28 | break; | 38 | break; |
29 | default: | 39 | default: |
30 | return -EINVAL; | 40 | return -EINVAL; |
@@ -47,22 +57,30 @@ static int test_power_get_battery_property(struct power_supply *psy, | |||
47 | val->strval = UTS_RELEASE; | 57 | val->strval = UTS_RELEASE; |
48 | break; | 58 | break; |
49 | case POWER_SUPPLY_PROP_STATUS: | 59 | case POWER_SUPPLY_PROP_STATUS: |
50 | val->intval = test_power_battery_status; | 60 | val->intval = battery_status; |
51 | break; | 61 | break; |
52 | case POWER_SUPPLY_PROP_CHARGE_TYPE: | 62 | case POWER_SUPPLY_PROP_CHARGE_TYPE: |
53 | val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST; | 63 | val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST; |
54 | break; | 64 | break; |
55 | case POWER_SUPPLY_PROP_HEALTH: | 65 | case POWER_SUPPLY_PROP_HEALTH: |
56 | val->intval = POWER_SUPPLY_HEALTH_GOOD; | 66 | val->intval = battery_health; |
67 | break; | ||
68 | case POWER_SUPPLY_PROP_PRESENT: | ||
69 | val->intval = battery_present; | ||
57 | break; | 70 | break; |
58 | case POWER_SUPPLY_PROP_TECHNOLOGY: | 71 | case POWER_SUPPLY_PROP_TECHNOLOGY: |
59 | val->intval = POWER_SUPPLY_TECHNOLOGY_LION; | 72 | val->intval = battery_technology; |
60 | break; | 73 | break; |
61 | case POWER_SUPPLY_PROP_CAPACITY_LEVEL: | 74 | case POWER_SUPPLY_PROP_CAPACITY_LEVEL: |
62 | val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; | 75 | val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; |
63 | break; | 76 | break; |
64 | case POWER_SUPPLY_PROP_CAPACITY: | 77 | case POWER_SUPPLY_PROP_CAPACITY: |
65 | val->intval = 50; | 78 | case POWER_SUPPLY_PROP_CHARGE_NOW: |
79 | val->intval = battery_capacity; | ||
80 | break; | ||
81 | case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: | ||
82 | case POWER_SUPPLY_PROP_CHARGE_FULL: | ||
83 | val->intval = 100; | ||
66 | break; | 84 | break; |
67 | case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: | 85 | case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: |
68 | case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW: | 86 | case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW: |
@@ -84,9 +102,11 @@ static enum power_supply_property test_power_battery_props[] = { | |||
84 | POWER_SUPPLY_PROP_STATUS, | 102 | POWER_SUPPLY_PROP_STATUS, |
85 | POWER_SUPPLY_PROP_CHARGE_TYPE, | 103 | POWER_SUPPLY_PROP_CHARGE_TYPE, |
86 | POWER_SUPPLY_PROP_HEALTH, | 104 | POWER_SUPPLY_PROP_HEALTH, |
105 | POWER_SUPPLY_PROP_PRESENT, | ||
87 | POWER_SUPPLY_PROP_TECHNOLOGY, | 106 | POWER_SUPPLY_PROP_TECHNOLOGY, |
107 | POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, | ||
88 | POWER_SUPPLY_PROP_CHARGE_FULL, | 108 | POWER_SUPPLY_PROP_CHARGE_FULL, |
89 | POWER_SUPPLY_PROP_CHARGE_EMPTY, | 109 | POWER_SUPPLY_PROP_CHARGE_NOW, |
90 | POWER_SUPPLY_PROP_CAPACITY, | 110 | POWER_SUPPLY_PROP_CAPACITY, |
91 | POWER_SUPPLY_PROP_CAPACITY_LEVEL, | 111 | POWER_SUPPLY_PROP_CAPACITY_LEVEL, |
92 | POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, | 112 | POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, |
@@ -118,6 +138,7 @@ static struct power_supply test_power_supplies[] = { | |||
118 | }, | 138 | }, |
119 | }; | 139 | }; |
120 | 140 | ||
141 | |||
121 | static int __init test_power_init(void) | 142 | static int __init test_power_init(void) |
122 | { | 143 | { |
123 | int i; | 144 | int i; |
@@ -145,8 +166,8 @@ static void __exit test_power_exit(void) | |||
145 | int i; | 166 | int i; |
146 | 167 | ||
147 | /* Let's see how we handle changes... */ | 168 | /* Let's see how we handle changes... */ |
148 | test_power_ac_online = 0; | 169 | ac_online = 0; |
149 | test_power_battery_status = POWER_SUPPLY_STATUS_DISCHARGING; | 170 | battery_status = POWER_SUPPLY_STATUS_DISCHARGING; |
150 | for (i = 0; i < ARRAY_SIZE(test_power_supplies); i++) | 171 | for (i = 0; i < ARRAY_SIZE(test_power_supplies); i++) |
151 | power_supply_changed(&test_power_supplies[i]); | 172 | power_supply_changed(&test_power_supplies[i]); |
152 | pr_info("%s: 'changed' event sent, sleeping for 10 seconds...\n", | 173 | pr_info("%s: 'changed' event sent, sleeping for 10 seconds...\n", |
@@ -158,6 +179,241 @@ static void __exit test_power_exit(void) | |||
158 | } | 179 | } |
159 | module_exit(test_power_exit); | 180 | module_exit(test_power_exit); |
160 | 181 | ||
182 | |||
183 | |||
184 | #define MAX_KEYLENGTH 256 | ||
185 | struct battery_property_map { | ||
186 | int value; | ||
187 | char const *key; | ||
188 | }; | ||
189 | |||
190 | static struct battery_property_map map_ac_online[] = { | ||
191 | { 0, "on" }, | ||
192 | { 1, "off" }, | ||
193 | { -1, NULL }, | ||
194 | }; | ||
195 | |||
196 | static struct battery_property_map map_status[] = { | ||
197 | { POWER_SUPPLY_STATUS_CHARGING, "charging" }, | ||
198 | { POWER_SUPPLY_STATUS_DISCHARGING, "discharging" }, | ||
199 | { POWER_SUPPLY_STATUS_NOT_CHARGING, "not-charging" }, | ||
200 | { POWER_SUPPLY_STATUS_FULL, "full" }, | ||
201 | { -1, NULL }, | ||
202 | }; | ||
203 | |||
204 | static struct battery_property_map map_health[] = { | ||
205 | { POWER_SUPPLY_HEALTH_GOOD, "good" }, | ||
206 | { POWER_SUPPLY_HEALTH_OVERHEAT, "overheat" }, | ||
207 | { POWER_SUPPLY_HEALTH_DEAD, "dead" }, | ||
208 | { POWER_SUPPLY_HEALTH_OVERVOLTAGE, "overvoltage" }, | ||
209 | { POWER_SUPPLY_HEALTH_UNSPEC_FAILURE, "failure" }, | ||
210 | { -1, NULL }, | ||
211 | }; | ||
212 | |||
213 | static struct battery_property_map map_present[] = { | ||
214 | { 0, "false" }, | ||
215 | { 1, "true" }, | ||
216 | { -1, NULL }, | ||
217 | }; | ||
218 | |||
219 | static struct battery_property_map map_technology[] = { | ||
220 | { POWER_SUPPLY_TECHNOLOGY_NiMH, "NiMH" }, | ||
221 | { POWER_SUPPLY_TECHNOLOGY_LION, "LION" }, | ||
222 | { POWER_SUPPLY_TECHNOLOGY_LIPO, "LIPO" }, | ||
223 | { POWER_SUPPLY_TECHNOLOGY_LiFe, "LiFe" }, | ||
224 | { POWER_SUPPLY_TECHNOLOGY_NiCd, "NiCd" }, | ||
225 | { POWER_SUPPLY_TECHNOLOGY_LiMn, "LiMn" }, | ||
226 | { -1, NULL }, | ||
227 | }; | ||
228 | |||
229 | |||
230 | static int map_get_value(struct battery_property_map *map, const char *key, | ||
231 | int def_val) | ||
232 | { | ||
233 | char buf[MAX_KEYLENGTH]; | ||
234 | int cr; | ||
235 | |||
236 | strncpy(buf, key, MAX_KEYLENGTH); | ||
237 | buf[MAX_KEYLENGTH-1] = '\0'; | ||
238 | |||
239 | cr = strnlen(buf, MAX_KEYLENGTH) - 1; | ||
240 | if (buf[cr] == '\n') | ||
241 | buf[cr] = '\0'; | ||
242 | |||
243 | while (map->key) { | ||
244 | if (strncasecmp(map->key, buf, MAX_KEYLENGTH) == 0) | ||
245 | return map->value; | ||
246 | map++; | ||
247 | } | ||
248 | |||
249 | return def_val; | ||
250 | } | ||
251 | |||
252 | |||
253 | static const char *map_get_key(struct battery_property_map *map, int value, | ||
254 | const char *def_key) | ||
255 | { | ||
256 | while (map->key) { | ||
257 | if (map->value == value) | ||
258 | return map->key; | ||
259 | map++; | ||
260 | } | ||
261 | |||
262 | return def_key; | ||
263 | } | ||
264 | |||
265 | static int param_set_ac_online(const char *key, const struct kernel_param *kp) | ||
266 | { | ||
267 | ac_online = map_get_value(map_ac_online, key, ac_online); | ||
268 | power_supply_changed(&test_power_supplies[0]); | ||
269 | return 0; | ||
270 | } | ||
271 | |||
272 | static int param_get_ac_online(char *buffer, const struct kernel_param *kp) | ||
273 | { | ||
274 | strcpy(buffer, map_get_key(map_ac_online, ac_online, "unknown")); | ||
275 | return strlen(buffer); | ||
276 | } | ||
277 | |||
278 | static int param_set_battery_status(const char *key, | ||
279 | const struct kernel_param *kp) | ||
280 | { | ||
281 | battery_status = map_get_value(map_status, key, battery_status); | ||
282 | power_supply_changed(&test_power_supplies[1]); | ||
283 | return 0; | ||
284 | } | ||
285 | |||
286 | static int param_get_battery_status(char *buffer, const struct kernel_param *kp) | ||
287 | { | ||
288 | strcpy(buffer, map_get_key(map_status, battery_status, "unknown")); | ||
289 | return strlen(buffer); | ||
290 | } | ||
291 | |||
292 | static int param_set_battery_health(const char *key, | ||
293 | const struct kernel_param *kp) | ||
294 | { | ||
295 | battery_health = map_get_value(map_health, key, battery_health); | ||
296 | power_supply_changed(&test_power_supplies[1]); | ||
297 | return 0; | ||
298 | } | ||
299 | |||
300 | static int param_get_battery_health(char *buffer, const struct kernel_param *kp) | ||
301 | { | ||
302 | strcpy(buffer, map_get_key(map_health, battery_health, "unknown")); | ||
303 | return strlen(buffer); | ||
304 | } | ||
305 | |||
306 | static int param_set_battery_present(const char *key, | ||
307 | const struct kernel_param *kp) | ||
308 | { | ||
309 | battery_present = map_get_value(map_present, key, battery_present); | ||
310 | power_supply_changed(&test_power_supplies[0]); | ||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | static int param_get_battery_present(char *buffer, | ||
315 | const struct kernel_param *kp) | ||
316 | { | ||
317 | strcpy(buffer, map_get_key(map_present, battery_present, "unknown")); | ||
318 | return strlen(buffer); | ||
319 | } | ||
320 | |||
321 | static int param_set_battery_technology(const char *key, | ||
322 | const struct kernel_param *kp) | ||
323 | { | ||
324 | battery_technology = map_get_value(map_technology, key, | ||
325 | battery_technology); | ||
326 | power_supply_changed(&test_power_supplies[1]); | ||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | static int param_get_battery_technology(char *buffer, | ||
331 | const struct kernel_param *kp) | ||
332 | { | ||
333 | strcpy(buffer, | ||
334 | map_get_key(map_technology, battery_technology, "unknown")); | ||
335 | return strlen(buffer); | ||
336 | } | ||
337 | |||
338 | static int param_set_battery_capacity(const char *key, | ||
339 | const struct kernel_param *kp) | ||
340 | { | ||
341 | int tmp; | ||
342 | |||
343 | if (1 != sscanf(key, "%d", &tmp)) | ||
344 | return -EINVAL; | ||
345 | |||
346 | battery_capacity = tmp; | ||
347 | power_supply_changed(&test_power_supplies[1]); | ||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | #define param_get_battery_capacity param_get_int | ||
352 | |||
353 | |||
354 | |||
355 | static struct kernel_param_ops param_ops_ac_online = { | ||
356 | .set = param_set_ac_online, | ||
357 | .get = param_get_ac_online, | ||
358 | }; | ||
359 | |||
360 | static struct kernel_param_ops param_ops_battery_status = { | ||
361 | .set = param_set_battery_status, | ||
362 | .get = param_get_battery_status, | ||
363 | }; | ||
364 | |||
365 | static struct kernel_param_ops param_ops_battery_present = { | ||
366 | .set = param_set_battery_present, | ||
367 | .get = param_get_battery_present, | ||
368 | }; | ||
369 | |||
370 | static struct kernel_param_ops param_ops_battery_technology = { | ||
371 | .set = param_set_battery_technology, | ||
372 | .get = param_get_battery_technology, | ||
373 | }; | ||
374 | |||
375 | static struct kernel_param_ops param_ops_battery_health = { | ||
376 | .set = param_set_battery_health, | ||
377 | .get = param_get_battery_health, | ||
378 | }; | ||
379 | |||
380 | static struct kernel_param_ops param_ops_battery_capacity = { | ||
381 | .set = param_set_battery_capacity, | ||
382 | .get = param_get_battery_capacity, | ||
383 | }; | ||
384 | |||
385 | |||
386 | #define param_check_ac_online(name, p) __param_check(name, p, void); | ||
387 | #define param_check_battery_status(name, p) __param_check(name, p, void); | ||
388 | #define param_check_battery_present(name, p) __param_check(name, p, void); | ||
389 | #define param_check_battery_technology(name, p) __param_check(name, p, void); | ||
390 | #define param_check_battery_health(name, p) __param_check(name, p, void); | ||
391 | #define param_check_battery_capacity(name, p) __param_check(name, p, void); | ||
392 | |||
393 | |||
394 | module_param(ac_online, ac_online, 0644); | ||
395 | MODULE_PARM_DESC(ac_online, "AC charging state <on|off>"); | ||
396 | |||
397 | module_param(battery_status, battery_status, 0644); | ||
398 | MODULE_PARM_DESC(battery_status, | ||
399 | "battery status <charging|discharging|not-charging|full>"); | ||
400 | |||
401 | module_param(battery_present, battery_present, 0644); | ||
402 | MODULE_PARM_DESC(battery_present, | ||
403 | "battery presence state <good|overheat|dead|overvoltage|failure>"); | ||
404 | |||
405 | module_param(battery_technology, battery_technology, 0644); | ||
406 | MODULE_PARM_DESC(battery_technology, | ||
407 | "battery technology <NiMH|LION|LIPO|LiFe|NiCd|LiMn>"); | ||
408 | |||
409 | module_param(battery_health, battery_health, 0644); | ||
410 | MODULE_PARM_DESC(battery_health, | ||
411 | "battery health state <good|overheat|dead|overvoltage|failure>"); | ||
412 | |||
413 | module_param(battery_capacity, battery_capacity, 0644); | ||
414 | MODULE_PARM_DESC(battery_capacity, "battery capacity (percentage)"); | ||
415 | |||
416 | |||
161 | MODULE_DESCRIPTION("Power supply driver for testing"); | 417 | MODULE_DESCRIPTION("Power supply driver for testing"); |
162 | MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>"); | 418 | MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>"); |
163 | MODULE_LICENSE("GPL"); | 419 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/power/z2_battery.c b/drivers/power/z2_battery.c index e5ced3a4c1ed..d119c38b3ff6 100644 --- a/drivers/power/z2_battery.c +++ b/drivers/power/z2_battery.c | |||
@@ -271,24 +271,33 @@ static int __devexit z2_batt_remove(struct i2c_client *client) | |||
271 | } | 271 | } |
272 | 272 | ||
273 | #ifdef CONFIG_PM | 273 | #ifdef CONFIG_PM |
274 | static int z2_batt_suspend(struct i2c_client *client, pm_message_t state) | 274 | static int z2_batt_suspend(struct device *dev) |
275 | { | 275 | { |
276 | struct i2c_client *client = to_i2c_client(dev); | ||
276 | struct z2_charger *charger = i2c_get_clientdata(client); | 277 | struct z2_charger *charger = i2c_get_clientdata(client); |
277 | 278 | ||
278 | flush_work_sync(&charger->bat_work); | 279 | flush_work_sync(&charger->bat_work); |
279 | return 0; | 280 | return 0; |
280 | } | 281 | } |
281 | 282 | ||
282 | static int z2_batt_resume(struct i2c_client *client) | 283 | static int z2_batt_resume(struct device *dev) |
283 | { | 284 | { |
285 | struct i2c_client *client = to_i2c_client(dev); | ||
284 | struct z2_charger *charger = i2c_get_clientdata(client); | 286 | struct z2_charger *charger = i2c_get_clientdata(client); |
285 | 287 | ||
286 | schedule_work(&charger->bat_work); | 288 | schedule_work(&charger->bat_work); |
287 | return 0; | 289 | return 0; |
288 | } | 290 | } |
291 | |||
292 | static const struct dev_pm_ops z2_battery_pm_ops = { | ||
293 | .suspend = z2_batt_suspend, | ||
294 | .resume = z2_batt_resume, | ||
295 | }; | ||
296 | |||
297 | #define Z2_BATTERY_PM_OPS (&z2_battery_pm_ops) | ||
298 | |||
289 | #else | 299 | #else |
290 | #define z2_batt_suspend NULL | 300 | #define Z2_BATTERY_PM_OPS (NULL) |
291 | #define z2_batt_resume NULL | ||
292 | #endif | 301 | #endif |
293 | 302 | ||
294 | static const struct i2c_device_id z2_batt_id[] = { | 303 | static const struct i2c_device_id z2_batt_id[] = { |
@@ -301,11 +310,10 @@ static struct i2c_driver z2_batt_driver = { | |||
301 | .driver = { | 310 | .driver = { |
302 | .name = "z2-battery", | 311 | .name = "z2-battery", |
303 | .owner = THIS_MODULE, | 312 | .owner = THIS_MODULE, |
313 | .pm = Z2_BATTERY_PM_OPS | ||
304 | }, | 314 | }, |
305 | .probe = z2_batt_probe, | 315 | .probe = z2_batt_probe, |
306 | .remove = z2_batt_remove, | 316 | .remove = z2_batt_remove, |
307 | .suspend = z2_batt_suspend, | ||
308 | .resume = z2_batt_resume, | ||
309 | .id_table = z2_batt_id, | 317 | .id_table = z2_batt_id, |
310 | }; | 318 | }; |
311 | 319 | ||