aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-05-27 13:12:35 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-05-27 13:12:35 -0400
commitea0ca3a843babd50c22dfbb5cf2d9a14df821b2b (patch)
tree0d27fc6d7b9a0a2cdfe29833eb84ee07beac91ab /drivers/power
parent74e6392ca3fd445a775dd42b54d5e42cf1e706e6 (diff)
parent906649de0eacde7a643b5a0750de6207441ad54f (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/Kconfig9
-rw-r--r--drivers/power/Makefile1
-rw-r--r--drivers/power/bq27x00_battery.c11
-rw-r--r--drivers/power/ds2760_battery.c6
-rw-r--r--drivers/power/gpio-charger.c15
-rw-r--r--drivers/power/isp1704_charger.c22
-rw-r--r--drivers/power/max8903_charger.c391
-rw-r--r--drivers/power/test_power.c276
-rw-r--r--drivers/power/z2_battery.c20
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
213config 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
213config CHARGER_TWL4030 222config 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
33obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o 33obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o
34obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o 34obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o
35obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o 35obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o
36obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o
36obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o 37obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o
37obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o 38obj-$(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
165static 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
176static SIMPLE_DEV_PM_OPS(gpio_charger_pm_ops, NULL, gpio_charger_resume);
177
164static struct platform_driver gpio_charger_driver = { 178static 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 */
78static 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
30struct 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
39static 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
45static 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
80static 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
121static 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
160static 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
181static __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
334err_usb_irq:
335 if (pdata->usb_valid)
336 free_irq(gpio_to_irq(pdata->uok), data);
337err_dc_irq:
338 if (pdata->dc_valid)
339 free_irq(gpio_to_irq(pdata->dok), data);
340err_psy:
341 power_supply_unregister(&data->psy);
342err:
343 kfree(data);
344 return ret;
345}
346
347static __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
367static 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
376static int __init max8903_init(void)
377{
378 return platform_driver_register(&max8903_driver);
379}
380module_init(max8903_init);
381
382static void __exit max8903_exit(void)
383{
384 platform_driver_unregister(&max8903_driver);
385}
386module_exit(max8903_exit);
387
388MODULE_LICENSE("GPL");
389MODULE_DESCRIPTION("MAX8903 Charger Driver");
390MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
391MODULE_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
18static int test_power_ac_online = 1; 24static int ac_online = 1;
19static int test_power_battery_status = POWER_SUPPLY_STATUS_CHARGING; 25static int battery_status = POWER_SUPPLY_STATUS_DISCHARGING;
26static int battery_health = POWER_SUPPLY_HEALTH_GOOD;
27static int battery_present = 1; /* true */
28static int battery_technology = POWER_SUPPLY_TECHNOLOGY_LION;
29static int battery_capacity = 50;
20 30
21static int test_power_get_ac_property(struct power_supply *psy, 31static 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
121static int __init test_power_init(void) 142static 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}
159module_exit(test_power_exit); 180module_exit(test_power_exit);
160 181
182
183
184#define MAX_KEYLENGTH 256
185struct battery_property_map {
186 int value;
187 char const *key;
188};
189
190static struct battery_property_map map_ac_online[] = {
191 { 0, "on" },
192 { 1, "off" },
193 { -1, NULL },
194};
195
196static 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
204static 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
213static struct battery_property_map map_present[] = {
214 { 0, "false" },
215 { 1, "true" },
216 { -1, NULL },
217};
218
219static 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
230static 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
253static 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
265static 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
272static 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
278static 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
286static 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
292static 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
300static 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
306static 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
314static 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
321static 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
330static 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
338static 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
355static struct kernel_param_ops param_ops_ac_online = {
356 .set = param_set_ac_online,
357 .get = param_get_ac_online,
358};
359
360static struct kernel_param_ops param_ops_battery_status = {
361 .set = param_set_battery_status,
362 .get = param_get_battery_status,
363};
364
365static struct kernel_param_ops param_ops_battery_present = {
366 .set = param_set_battery_present,
367 .get = param_get_battery_present,
368};
369
370static struct kernel_param_ops param_ops_battery_technology = {
371 .set = param_set_battery_technology,
372 .get = param_get_battery_technology,
373};
374
375static struct kernel_param_ops param_ops_battery_health = {
376 .set = param_set_battery_health,
377 .get = param_get_battery_health,
378};
379
380static 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
394module_param(ac_online, ac_online, 0644);
395MODULE_PARM_DESC(ac_online, "AC charging state <on|off>");
396
397module_param(battery_status, battery_status, 0644);
398MODULE_PARM_DESC(battery_status,
399 "battery status <charging|discharging|not-charging|full>");
400
401module_param(battery_present, battery_present, 0644);
402MODULE_PARM_DESC(battery_present,
403 "battery presence state <good|overheat|dead|overvoltage|failure>");
404
405module_param(battery_technology, battery_technology, 0644);
406MODULE_PARM_DESC(battery_technology,
407 "battery technology <NiMH|LION|LIPO|LiFe|NiCd|LiMn>");
408
409module_param(battery_health, battery_health, 0644);
410MODULE_PARM_DESC(battery_health,
411 "battery health state <good|overheat|dead|overvoltage|failure>");
412
413module_param(battery_capacity, battery_capacity, 0644);
414MODULE_PARM_DESC(battery_capacity, "battery capacity (percentage)");
415
416
161MODULE_DESCRIPTION("Power supply driver for testing"); 417MODULE_DESCRIPTION("Power supply driver for testing");
162MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>"); 418MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>");
163MODULE_LICENSE("GPL"); 419MODULE_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
274static int z2_batt_suspend(struct i2c_client *client, pm_message_t state) 274static 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
282static int z2_batt_resume(struct i2c_client *client) 283static 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
292static 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
294static const struct i2c_device_id z2_batt_id[] = { 303static 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