aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-01-11 21:53:05 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-01-11 21:53:05 -0500
commitb24ca57e7625bc304e77bc429693ad32a691eb16 (patch)
tree770aa389c6e763cf37776a35e85ff1e41958b1e9
parent6296e5d3c067df41980a5fd09ad4cc6765f79bb9 (diff)
parent913272b3864d6da89c70d9fc2c30ccb57794b369 (diff)
Merge git://git.infradead.org/battery-2.6
* git://git.infradead.org/battery-2.6: (68 commits) power_supply: Mark da9052 driver as broken power_supply: Drop usage of nowarn variant of sysfs_create_link() s3c_adc_battery: Average over more than one adc sample power_supply: Add DA9052 battery driver isp1704_charger: Fix missing check jz4740-battery: Fix signedness bug power_supply: Assume mains power by default sbs-battery: Fix devicetree match table ARM: rx51: Add bq27200 i2c board info sbs-battery: Change power supply name devicetree-bindings: Propagate bq20z75->sbs rename to dt bindings devicetree-bindings: Add vendor entry for Smart Battery Systems sbs-battery: Rename internals to new name bq20z75: Rename to sbs-battery wm97xx_battery: Use DEFINE_MUTEX() for work_lock max8997_charger: Remove duplicate module.h lp8727_charger: Some minor fixes for the header lp8727_charger: Add header file power_supply: Convert drivers/power/* to use module_platform_driver() power_supply: Add "unknown" in power supply type ...
-rw-r--r--Documentation/devicetree/bindings/power_supply/olpc_battery.txt5
-rw-r--r--Documentation/devicetree/bindings/power_supply/sbs_sbs-battery.txt23
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.txt1
-rw-r--r--Documentation/power/charger-manager.txt163
-rw-r--r--arch/arm/mach-omap2/board-rx51-peripherals.c3
-rw-r--r--drivers/hid/hid-wacom.c16
-rw-r--r--drivers/hid/hid-wiimote-core.c10
-rw-r--r--drivers/mfd/max8925-core.c15
-rw-r--r--drivers/power/Kconfig32
-rw-r--r--drivers/power/Makefile5
-rw-r--r--drivers/power/bq27x00_battery.c210
-rw-r--r--drivers/power/charger-manager.c1072
-rw-r--r--drivers/power/collie_battery.c55
-rw-r--r--drivers/power/da9030_battery.c13
-rw-r--r--drivers/power/da9052-battery.c664
-rw-r--r--drivers/power/ds2760_battery.c19
-rw-r--r--drivers/power/ds2780_battery.c18
-rw-r--r--drivers/power/gpio-charger.c12
-rw-r--r--drivers/power/intel_mid_battery.c13
-rw-r--r--drivers/power/isp1704_charger.c14
-rw-r--r--drivers/power/jz4740-battery.c14
-rw-r--r--drivers/power/lp8727_charger.c494
-rw-r--r--drivers/power/max17042_battery.c94
-rw-r--r--drivers/power/max8903_charger.c14
-rw-r--r--drivers/power/max8925_power.c75
-rw-r--r--drivers/power/max8997_charger.c4
-rw-r--r--drivers/power/max8998_charger.c14
-rw-r--r--drivers/power/olpc_battery.c75
-rw-r--r--drivers/power/pcf50633-charger.c12
-rw-r--r--drivers/power/pda_power.c89
-rw-r--r--drivers/power/power_supply_core.c19
-rw-r--r--drivers/power/power_supply_sysfs.c12
-rw-r--r--drivers/power/s3c_adc_battery.c37
-rw-r--r--drivers/power/sbs-battery.c (renamed from drivers/power/bq20z75.c)481
-rw-r--r--drivers/power/tosa_battery.c79
-rw-r--r--drivers/power/wm831x_backup.c12
-rw-r--r--drivers/power/wm831x_power.c56
-rw-r--r--drivers/power/wm8350_power.c12
-rw-r--r--drivers/power/wm97xx_battery.c20
-rw-r--r--drivers/power/z2_battery.c4
-rwxr-xr-xinclude/linux/lp8727.h51
-rw-r--r--include/linux/mfd/max8925.h7
-rw-r--r--include/linux/pda_power.h2
-rw-r--r--include/linux/power/charger-manager.h147
-rw-r--r--include/linux/power/sbs-battery.h (renamed from include/linux/power/bq20z75.h)10
-rw-r--r--include/linux/power_supply.h11
-rw-r--r--include/linux/s3c_adc_battery.h4
47 files changed, 3475 insertions, 737 deletions
diff --git a/Documentation/devicetree/bindings/power_supply/olpc_battery.txt b/Documentation/devicetree/bindings/power_supply/olpc_battery.txt
new file mode 100644
index 00000000000..c8901b3992d
--- /dev/null
+++ b/Documentation/devicetree/bindings/power_supply/olpc_battery.txt
@@ -0,0 +1,5 @@
1OLPC battery
2~~~~~~~~~~~~
3
4Required properties:
5 - compatible : "olpc,xo1-battery"
diff --git a/Documentation/devicetree/bindings/power_supply/sbs_sbs-battery.txt b/Documentation/devicetree/bindings/power_supply/sbs_sbs-battery.txt
new file mode 100644
index 00000000000..c40e8926fac
--- /dev/null
+++ b/Documentation/devicetree/bindings/power_supply/sbs_sbs-battery.txt
@@ -0,0 +1,23 @@
1SBS sbs-battery
2~~~~~~~~~~
3
4Required properties :
5 - compatible : "sbs,sbs-battery"
6
7Optional properties :
8 - sbs,i2c-retry-count : The number of times to retry i2c transactions on i2c
9 IO failure.
10 - sbs,poll-retry-count : The number of times to try looking for new status
11 after an external change notification.
12 - sbs,battery-detect-gpios : The gpio which signals battery detection and
13 a flag specifying its polarity.
14
15Example:
16
17 bq20z75@b {
18 compatible = "sbs,sbs-battery";
19 reg = < 0xb >;
20 sbs,i2c-retry-count = <2>;
21 sbs,poll-retry-count = <10>;
22 sbs,battery-detect-gpios = <&gpio-controller 122 1>;
23 }
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 18626965159..6fdb450b05f 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -34,6 +34,7 @@ powervr Imagination Technologies
34qcom Qualcomm, Inc. 34qcom Qualcomm, Inc.
35ramtron Ramtron International 35ramtron Ramtron International
36samsung Samsung Semiconductor 36samsung Samsung Semiconductor
37sbs Smart Battery System
37schindler Schindler 38schindler Schindler
38sil Silicon Image 39sil Silicon Image
39simtek 40simtek
diff --git a/Documentation/power/charger-manager.txt b/Documentation/power/charger-manager.txt
new file mode 100644
index 00000000000..fdcca991df3
--- /dev/null
+++ b/Documentation/power/charger-manager.txt
@@ -0,0 +1,163 @@
1Charger Manager
2 (C) 2011 MyungJoo Ham <myungjoo.ham@samsung.com>, GPL
3
4Charger Manager provides in-kernel battery charger management that
5requires temperature monitoring during suspend-to-RAM state
6and where each battery may have multiple chargers attached and the userland
7wants to look at the aggregated information of the multiple chargers.
8
9Charger Manager is a platform_driver with power-supply-class entries.
10An instance of Charger Manager (a platform-device created with Charger-Manager)
11represents an independent battery with chargers. If there are multiple
12batteries with their own chargers acting independently in a system,
13the system may need multiple instances of Charger Manager.
14
151. Introduction
16===============
17
18Charger Manager supports the following:
19
20* Support for multiple chargers (e.g., a device with USB, AC, and solar panels)
21 A system may have multiple chargers (or power sources) and some of
22 they may be activated at the same time. Each charger may have its
23 own power-supply-class and each power-supply-class can provide
24 different information about the battery status. This framework
25 aggregates charger-related information from multiple sources and
26 shows combined information as a single power-supply-class.
27
28* Support for in suspend-to-RAM polling (with suspend_again callback)
29 While the battery is being charged and the system is in suspend-to-RAM,
30 we may need to monitor the battery health by looking at the ambient or
31 battery temperature. We can accomplish this by waking up the system
32 periodically. However, such a method wakes up devices unncessary for
33 monitoring the battery health and tasks, and user processes that are
34 supposed to be kept suspended. That, in turn, incurs unnecessary power
35 consumption and slow down charging process. Or even, such peak power
36 consumption can stop chargers in the middle of charging
37 (external power input < device power consumption), which not
38 only affects the charging time, but the lifespan of the battery.
39
40 Charger Manager provides a function "cm_suspend_again" that can be
41 used as suspend_again callback of platform_suspend_ops. If the platform
42 requires tasks other than cm_suspend_again, it may implement its own
43 suspend_again callback that calls cm_suspend_again in the middle.
44 Normally, the platform will need to resume and suspend some devices
45 that are used by Charger Manager.
46
472. Global Charger-Manager Data related with suspend_again
48========================================================
49In order to setup Charger Manager with suspend-again feature
50(in-suspend monitoring), the user should provide charger_global_desc
51with setup_charger_manager(struct charger_global_desc *).
52This charger_global_desc data for in-suspend monitoring is global
53as the name suggests. Thus, the user needs to provide only once even
54if there are multiple batteries. If there are multiple batteries, the
55multiple instances of Charger Manager share the same charger_global_desc
56and it will manage in-suspend monitoring for all instances of Charger Manager.
57
58The user needs to provide all the two entries properly in order to activate
59in-suspend monitoring:
60
61struct charger_global_desc {
62
63char *rtc_name;
64 : The name of rtc (e.g., "rtc0") used to wakeup the system from
65 suspend for Charger Manager. The alarm interrupt (AIE) of the rtc
66 should be able to wake up the system from suspend. Charger Manager
67 saves and restores the alarm value and use the previously-defined
68 alarm if it is going to go off earlier than Charger Manager so that
69 Charger Manager does not interfere with previously-defined alarms.
70
71bool (*rtc_only_wakeup)(void);
72 : This callback should let CM know whether
73 the wakeup-from-suspend is caused only by the alarm of "rtc" in the
74 same struct. If there is any other wakeup source triggered the
75 wakeup, it should return false. If the "rtc" is the only wakeup
76 reason, it should return true.
77};
78
793. How to setup suspend_again
80=============================
81Charger Manager provides a function "extern bool cm_suspend_again(void)".
82When cm_suspend_again is called, it monitors every battery. The suspend_ops
83callback of the system's platform_suspend_ops can call cm_suspend_again
84function to know whether Charger Manager wants to suspend again or not.
85If there are no other devices or tasks that want to use suspend_again
86feature, the platform_suspend_ops may directly refer to cm_suspend_again
87for its suspend_again callback.
88
89The cm_suspend_again() returns true (meaning "I want to suspend again")
90if the system was woken up by Charger Manager and the polling
91(in-suspend monitoring) results in "normal".
92
934. Charger-Manager Data (struct charger_desc)
94=============================================
95For each battery charged independently from other batteries (if a series of
96batteries are charged by a single charger, they are counted as one independent
97battery), an instance of Charger Manager is attached to it.
98
99struct charger_desc {
100
101char *psy_name;
102 : The power-supply-class name of the battery. Default is
103 "battery" if psy_name is NULL. Users can access the psy entries
104 at "/sys/class/power_supply/[psy_name]/".
105
106enum polling_modes polling_mode;
107 : CM_POLL_DISABLE: do not poll this battery.
108 CM_POLL_ALWAYS: always poll this battery.
109 CM_POLL_EXTERNAL_POWER_ONLY: poll this battery if and only if
110 an external power source is attached.
111 CM_POLL_CHARGING_ONLY: poll this battery if and only if the
112 battery is being charged.
113
114unsigned int fullbatt_uV;
115 : If specified with a non-zero value, Charger Manager assumes
116 that the battery is full (capacity = 100) if the battery is not being
117 charged and the battery voltage is equal to or greater than
118 fullbatt_uV.
119
120unsigned int polling_interval_ms;
121 : Required polling interval in ms. Charger Manager will poll
122 this battery every polling_interval_ms or more frequently.
123
124enum data_source battery_present;
125 CM_FUEL_GAUGE: get battery presence information from fuel gauge.
126 CM_CHARGER_STAT: get battery presence from chargers.
127
128char **psy_charger_stat;
129 : An array ending with NULL that has power-supply-class names of
130 chargers. Each power-supply-class should provide "PRESENT" (if
131 battery_present is "CM_CHARGER_STAT"), "ONLINE" (shows whether an
132 external power source is attached or not), and "STATUS" (shows whether
133 the battery is {"FULL" or not FULL} or {"FULL", "Charging",
134 "Discharging", "NotCharging"}).
135
136int num_charger_regulators;
137struct regulator_bulk_data *charger_regulators;
138 : Regulators representing the chargers in the form for
139 regulator framework's bulk functions.
140
141char *psy_fuel_gauge;
142 : Power-supply-class name of the fuel gauge.
143
144int (*temperature_out_of_range)(int *mC);
145bool measure_battery_temp;
146 : This callback returns 0 if the temperature is safe for charging,
147 a positive number if it is too hot to charge, and a negative number
148 if it is too cold to charge. With the variable mC, the callback returns
149 the temperature in 1/1000 of centigrade.
150 The source of temperature can be battery or ambient one according to
151 the value of measure_battery_temp.
152};
153
1545. Other Considerations
155=======================
156
157At the charger/battery-related events such as battery-pulled-out,
158charger-pulled-out, charger-inserted, DCIN-over/under-voltage, charger-stopped,
159and others critical to chargers, the system should be configured to wake up.
160At least the following should wake up the system from a suspend:
161a) charger-on/off b) external-power-in/out c) battery-in/out (while charging)
162
163It is usually accomplished by configuring the PMIC as a wakeup source.
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index d67bcdf724d..acb4e77b39e 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -945,6 +945,9 @@ static struct i2c_board_info __initdata rx51_peripherals_i2c_board_info_2[] = {
945 }, 945 },
946#endif 946#endif
947 { 947 {
948 I2C_BOARD_INFO("bq27200", 0x55),
949 },
950 {
948 I2C_BOARD_INFO("tpa6130a2", 0x60), 951 I2C_BOARD_INFO("tpa6130a2", 0x60),
949 .platform_data = &rx51_tpa6130a2_data, 952 .platform_data = &rx51_tpa6130a2_data,
950 } 953 }
diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c
index f2183486a9b..b47e58b52d9 100644
--- a/drivers/hid/hid-wacom.c
+++ b/drivers/hid/hid-wacom.c
@@ -49,12 +49,14 @@ static unsigned short batcap[8] = { 1, 15, 25, 35, 50, 70, 100, 0 };
49 49
50static enum power_supply_property wacom_battery_props[] = { 50static enum power_supply_property wacom_battery_props[] = {
51 POWER_SUPPLY_PROP_PRESENT, 51 POWER_SUPPLY_PROP_PRESENT,
52 POWER_SUPPLY_PROP_CAPACITY 52 POWER_SUPPLY_PROP_CAPACITY,
53 POWER_SUPPLY_PROP_SCOPE,
53}; 54};
54 55
55static enum power_supply_property wacom_ac_props[] = { 56static enum power_supply_property wacom_ac_props[] = {
56 POWER_SUPPLY_PROP_PRESENT, 57 POWER_SUPPLY_PROP_PRESENT,
57 POWER_SUPPLY_PROP_ONLINE 58 POWER_SUPPLY_PROP_ONLINE,
59 POWER_SUPPLY_PROP_SCOPE,
58}; 60};
59 61
60static int wacom_battery_get_property(struct power_supply *psy, 62static int wacom_battery_get_property(struct power_supply *psy,
@@ -70,6 +72,9 @@ static int wacom_battery_get_property(struct power_supply *psy,
70 case POWER_SUPPLY_PROP_PRESENT: 72 case POWER_SUPPLY_PROP_PRESENT:
71 val->intval = 1; 73 val->intval = 1;
72 break; 74 break;
75 case POWER_SUPPLY_PROP_SCOPE:
76 val->intval = POWER_SUPPLY_SCOPE_DEVICE;
77 break;
73 case POWER_SUPPLY_PROP_CAPACITY: 78 case POWER_SUPPLY_PROP_CAPACITY:
74 /* show 100% battery capacity when charging */ 79 /* show 100% battery capacity when charging */
75 if (power_state == 0) 80 if (power_state == 0)
@@ -101,6 +106,9 @@ static int wacom_ac_get_property(struct power_supply *psy,
101 else 106 else
102 val->intval = 0; 107 val->intval = 0;
103 break; 108 break;
109 case POWER_SUPPLY_PROP_SCOPE:
110 val->intval = POWER_SUPPLY_SCOPE_DEVICE;
111 break;
104 default: 112 default:
105 ret = -EINVAL; 113 ret = -EINVAL;
106 break; 114 break;
@@ -523,6 +531,8 @@ static int wacom_probe(struct hid_device *hdev,
523 wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY; 531 wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY;
524 wdata->battery.use_for_apm = 0; 532 wdata->battery.use_for_apm = 0;
525 533
534 power_supply_powers(&wdata->battery, &hdev->dev);
535
526 ret = power_supply_register(&hdev->dev, &wdata->battery); 536 ret = power_supply_register(&hdev->dev, &wdata->battery);
527 if (ret) { 537 if (ret) {
528 hid_warn(hdev, "can't create sysfs battery attribute, err: %d\n", 538 hid_warn(hdev, "can't create sysfs battery attribute, err: %d\n",
@@ -537,6 +547,8 @@ static int wacom_probe(struct hid_device *hdev,
537 wdata->ac.type = POWER_SUPPLY_TYPE_MAINS; 547 wdata->ac.type = POWER_SUPPLY_TYPE_MAINS;
538 wdata->ac.use_for_apm = 0; 548 wdata->ac.use_for_apm = 0;
539 549
550 power_supply_powers(&wdata->battery, &hdev->dev);
551
540 ret = power_supply_register(&hdev->dev, &wdata->ac); 552 ret = power_supply_register(&hdev->dev, &wdata->ac);
541 if (ret) { 553 if (ret) {
542 hid_warn(hdev, 554 hid_warn(hdev,
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c
index 61881b35c67..fc253b472f9 100644
--- a/drivers/hid/hid-wiimote-core.c
+++ b/drivers/hid/hid-wiimote-core.c
@@ -52,7 +52,8 @@ static __u16 wiiproto_keymap[] = {
52}; 52};
53 53
54static enum power_supply_property wiimote_battery_props[] = { 54static enum power_supply_property wiimote_battery_props[] = {
55 POWER_SUPPLY_PROP_CAPACITY 55 POWER_SUPPLY_PROP_CAPACITY,
56 POWER_SUPPLY_PROP_SCOPE,
56}; 57};
57 58
58static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, 59static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer,
@@ -402,6 +403,11 @@ static int wiimote_battery_get_property(struct power_supply *psy,
402 int ret = 0, state; 403 int ret = 0, state;
403 unsigned long flags; 404 unsigned long flags;
404 405
406 if (psp == POWER_SUPPLY_PROP_SCOPE) {
407 val->intval = POWER_SUPPLY_SCOPE_DEVICE;
408 return 0;
409 }
410
405 ret = wiimote_cmd_acquire(wdata); 411 ret = wiimote_cmd_acquire(wdata);
406 if (ret) 412 if (ret)
407 return ret; 413 return ret;
@@ -1220,6 +1226,8 @@ static int wiimote_hid_probe(struct hid_device *hdev,
1220 wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY; 1226 wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY;
1221 wdata->battery.use_for_apm = 0; 1227 wdata->battery.use_for_apm = 0;
1222 1228
1229 power_supply_powers(&wdata->battery, &hdev->dev);
1230
1223 ret = power_supply_register(&wdata->hdev->dev, &wdata->battery); 1231 ret = power_supply_register(&wdata->hdev->dev, &wdata->battery);
1224 if (ret) { 1232 if (ret) {
1225 hid_err(hdev, "Cannot register battery device\n"); 1233 hid_err(hdev, "Cannot register battery device\n");
diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c
index e1e59c92f75..ca881efedf7 100644
--- a/drivers/mfd/max8925-core.c
+++ b/drivers/mfd/max8925-core.c
@@ -210,21 +210,6 @@ static struct max8925_irq_data max8925_irqs[] = {
210 .mask_reg = MAX8925_CHG_IRQ1_MASK, 210 .mask_reg = MAX8925_CHG_IRQ1_MASK,
211 .offs = 1 << 2, 211 .offs = 1 << 2,
212 }, 212 },
213 [MAX8925_IRQ_VCHG_USB_OVP] = {
214 .reg = MAX8925_CHG_IRQ1,
215 .mask_reg = MAX8925_CHG_IRQ1_MASK,
216 .offs = 1 << 3,
217 },
218 [MAX8925_IRQ_VCHG_USB_F] = {
219 .reg = MAX8925_CHG_IRQ1,
220 .mask_reg = MAX8925_CHG_IRQ1_MASK,
221 .offs = 1 << 4,
222 },
223 [MAX8925_IRQ_VCHG_USB_R] = {
224 .reg = MAX8925_CHG_IRQ1,
225 .mask_reg = MAX8925_CHG_IRQ1_MASK,
226 .offs = 1 << 5,
227 },
228 [MAX8925_IRQ_VCHG_THM_OK_R] = { 213 [MAX8925_IRQ_VCHG_THM_OK_R] = {
229 .reg = MAX8925_CHG_IRQ2, 214 .reg = MAX8925_CHG_IRQ2,
230 .mask_reg = MAX8925_CHG_IRQ2_MASK, 215 .mask_reg = MAX8925_CHG_IRQ2_MASK,
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 9f88641e67f..3a8daf85874 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -116,12 +116,12 @@ config BATTERY_WM97XX
116 help 116 help
117 Say Y to enable support for battery measured by WM97xx aux port. 117 Say Y to enable support for battery measured by WM97xx aux port.
118 118
119config BATTERY_BQ20Z75 119config BATTERY_SBS
120 tristate "TI BQ20z75 gas gauge" 120 tristate "SBS Compliant gas gauge"
121 depends on I2C 121 depends on I2C
122 help 122 help
123 Say Y to include support for TI BQ20z75 SBS-compliant 123 Say Y to include support for SBS battery driver for SBS-compliant
124 gas gauge and protection IC. 124 gas gauges.
125 125
126config BATTERY_BQ27x00 126config BATTERY_BQ27x00
127 tristate "BQ27x00 battery driver" 127 tristate "BQ27x00 battery driver"
@@ -150,6 +150,14 @@ config BATTERY_DA9030
150 Say Y here to enable support for batteries charger integrated into 150 Say Y here to enable support for batteries charger integrated into
151 DA9030 PMIC. 151 DA9030 PMIC.
152 152
153config BATTERY_DA9052
154 tristate "Dialog DA9052 Battery"
155 depends on PMIC_DA9052
156 depends on BROKEN
157 help
158 Say Y here to enable support for batteries charger integrated into
159 DA9052 PMIC.
160
153config BATTERY_MAX17040 161config BATTERY_MAX17040
154 tristate "Maxim MAX17040 Fuel Gauge" 162 tristate "Maxim MAX17040 Fuel Gauge"
155 depends on I2C 163 depends on I2C
@@ -226,6 +234,12 @@ config CHARGER_TWL4030
226 help 234 help
227 Say Y here to enable support for TWL4030 Battery Charge Interface. 235 Say Y here to enable support for TWL4030 Battery Charge Interface.
228 236
237config CHARGER_LP8727
238 tristate "National Semiconductor LP8727 charger driver"
239 depends on I2C
240 help
241 Say Y here to enable support for LP8727 Charger Driver.
242
229config CHARGER_GPIO 243config CHARGER_GPIO
230 tristate "GPIO charger" 244 tristate "GPIO charger"
231 depends on GPIOLIB 245 depends on GPIOLIB
@@ -236,6 +250,16 @@ config CHARGER_GPIO
236 This driver can be build as a module. If so, the module will be 250 This driver can be build as a module. If so, the module will be
237 called gpio-charger. 251 called gpio-charger.
238 252
253config CHARGER_MANAGER
254 bool "Battery charger manager for multiple chargers"
255 depends on REGULATOR && RTC_CLASS
256 help
257 Say Y to enable charger-manager support, which allows multiple
258 chargers attached to a battery and multiple batteries attached to a
259 system. The charger-manager also can monitor charging status in
260 runtime and in suspend-to-RAM by waking up the system periodically
261 with help of suspend_again support.
262
239config CHARGER_MAX8997 263config CHARGER_MAX8997
240 tristate "Maxim MAX8997/MAX8966 PMIC battery charger driver" 264 tristate "Maxim MAX8997/MAX8966 PMIC battery charger driver"
241 depends on MFD_MAX8997 && REGULATOR_MAX8997 265 depends on MFD_MAX8997 && REGULATOR_MAX8997
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index b4af13dd8b6..e429008eaf1 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -22,9 +22,10 @@ obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o
22obj-$(CONFIG_BATTERY_TOSA) += tosa_battery.o 22obj-$(CONFIG_BATTERY_TOSA) += tosa_battery.o
23obj-$(CONFIG_BATTERY_COLLIE) += collie_battery.o 23obj-$(CONFIG_BATTERY_COLLIE) += collie_battery.o
24obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o 24obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o
25obj-$(CONFIG_BATTERY_BQ20Z75) += bq20z75.o 25obj-$(CONFIG_BATTERY_SBS) += sbs-battery.o
26obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o 26obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o
27obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o 27obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o
28obj-$(CONFIG_BATTERY_DA9052) += da9052-battery.o
28obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o 29obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o
29obj-$(CONFIG_BATTERY_MAX17042) += max17042_battery.o 30obj-$(CONFIG_BATTERY_MAX17042) += max17042_battery.o
30obj-$(CONFIG_BATTERY_Z2) += z2_battery.o 31obj-$(CONFIG_BATTERY_Z2) += z2_battery.o
@@ -35,6 +36,8 @@ obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o
35obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o 36obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o
36obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o 37obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o
37obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o 38obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o
39obj-$(CONFIG_CHARGER_LP8727) += lp8727_charger.o
38obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o 40obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o
41obj-$(CONFIG_CHARGER_MANAGER) += charger-manager.o
39obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o 42obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o
40obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o 43obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c
index bb16f5b7e16..98bf5676318 100644
--- a/drivers/power/bq27x00_battery.c
+++ b/drivers/power/bq27x00_battery.c
@@ -54,13 +54,19 @@
54 54
55#define BQ27000_REG_RSOC 0x0B /* Relative State-of-Charge */ 55#define BQ27000_REG_RSOC 0x0B /* Relative State-of-Charge */
56#define BQ27000_REG_ILMD 0x76 /* Initial last measured discharge */ 56#define BQ27000_REG_ILMD 0x76 /* Initial last measured discharge */
57#define BQ27000_FLAG_CHGS BIT(7) 57#define BQ27000_FLAG_EDVF BIT(0) /* Final End-of-Discharge-Voltage flag */
58#define BQ27000_FLAG_EDV1 BIT(1) /* First End-of-Discharge-Voltage flag */
59#define BQ27000_FLAG_CI BIT(4) /* Capacity Inaccurate flag */
58#define BQ27000_FLAG_FC BIT(5) 60#define BQ27000_FLAG_FC BIT(5)
61#define BQ27000_FLAG_CHGS BIT(7) /* Charge state flag */
59 62
60#define BQ27500_REG_SOC 0x2C 63#define BQ27500_REG_SOC 0x2C
61#define BQ27500_REG_DCAP 0x3C /* Design capacity */ 64#define BQ27500_REG_DCAP 0x3C /* Design capacity */
62#define BQ27500_FLAG_DSC BIT(0) 65#define BQ27500_FLAG_DSG BIT(0) /* Discharging */
63#define BQ27500_FLAG_FC BIT(9) 66#define BQ27500_FLAG_SOCF BIT(1) /* State-of-Charge threshold final */
67#define BQ27500_FLAG_SOC1 BIT(2) /* State-of-Charge threshold 1 */
68#define BQ27500_FLAG_CHG BIT(8) /* Charging */
69#define BQ27500_FLAG_FC BIT(9) /* Fully charged */
64 70
65#define BQ27000_RS 20 /* Resistor sense */ 71#define BQ27000_RS 20 /* Resistor sense */
66 72
@@ -79,9 +85,8 @@ struct bq27x00_reg_cache {
79 int charge_full; 85 int charge_full;
80 int cycle_count; 86 int cycle_count;
81 int capacity; 87 int capacity;
88 int energy;
82 int flags; 89 int flags;
83
84 int current_now;
85}; 90};
86 91
87struct bq27x00_device_info { 92struct bq27x00_device_info {
@@ -108,6 +113,7 @@ static enum power_supply_property bq27x00_battery_props[] = {
108 POWER_SUPPLY_PROP_VOLTAGE_NOW, 113 POWER_SUPPLY_PROP_VOLTAGE_NOW,
109 POWER_SUPPLY_PROP_CURRENT_NOW, 114 POWER_SUPPLY_PROP_CURRENT_NOW,
110 POWER_SUPPLY_PROP_CAPACITY, 115 POWER_SUPPLY_PROP_CAPACITY,
116 POWER_SUPPLY_PROP_CAPACITY_LEVEL,
111 POWER_SUPPLY_PROP_TEMP, 117 POWER_SUPPLY_PROP_TEMP,
112 POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, 118 POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
113 POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, 119 POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
@@ -149,7 +155,7 @@ static int bq27x00_battery_read_rsoc(struct bq27x00_device_info *di)
149 rsoc = bq27x00_read(di, BQ27000_REG_RSOC, true); 155 rsoc = bq27x00_read(di, BQ27000_REG_RSOC, true);
150 156
151 if (rsoc < 0) 157 if (rsoc < 0)
152 dev_err(di->dev, "error reading relative State-of-Charge\n"); 158 dev_dbg(di->dev, "error reading relative State-of-Charge\n");
153 159
154 return rsoc; 160 return rsoc;
155} 161}
@@ -164,7 +170,8 @@ static int bq27x00_battery_read_charge(struct bq27x00_device_info *di, u8 reg)
164 170
165 charge = bq27x00_read(di, reg, false); 171 charge = bq27x00_read(di, reg, false);
166 if (charge < 0) { 172 if (charge < 0) {
167 dev_err(di->dev, "error reading nominal available capacity\n"); 173 dev_dbg(di->dev, "error reading charge register %02x: %d\n",
174 reg, charge);
168 return charge; 175 return charge;
169 } 176 }
170 177
@@ -208,7 +215,7 @@ static int bq27x00_battery_read_ilmd(struct bq27x00_device_info *di)
208 ilmd = bq27x00_read(di, BQ27000_REG_ILMD, true); 215 ilmd = bq27x00_read(di, BQ27000_REG_ILMD, true);
209 216
210 if (ilmd < 0) { 217 if (ilmd < 0) {
211 dev_err(di->dev, "error reading initial last measured discharge\n"); 218 dev_dbg(di->dev, "error reading initial last measured discharge\n");
212 return ilmd; 219 return ilmd;
213 } 220 }
214 221
@@ -221,6 +228,50 @@ static int bq27x00_battery_read_ilmd(struct bq27x00_device_info *di)
221} 228}
222 229
223/* 230/*
231 * Return the battery Available energy in µWh
232 * Or < 0 if something fails.
233 */
234static int bq27x00_battery_read_energy(struct bq27x00_device_info *di)
235{
236 int ae;
237
238 ae = bq27x00_read(di, BQ27x00_REG_AE, false);
239 if (ae < 0) {
240 dev_dbg(di->dev, "error reading available energy\n");
241 return ae;
242 }
243
244 if (di->chip == BQ27500)
245 ae *= 1000;
246 else
247 ae = ae * 29200 / BQ27000_RS;
248
249 return ae;
250}
251
252/*
253 * Return the battery temperature in tenths of degree Celsius
254 * Or < 0 if something fails.
255 */
256static int bq27x00_battery_read_temperature(struct bq27x00_device_info *di)
257{
258 int temp;
259
260 temp = bq27x00_read(di, BQ27x00_REG_TEMP, false);
261 if (temp < 0) {
262 dev_err(di->dev, "error reading temperature\n");
263 return temp;
264 }
265
266 if (di->chip == BQ27500)
267 temp -= 2731;
268 else
269 temp = ((temp * 5) - 5463) / 2;
270
271 return temp;
272}
273
274/*
224 * Return the battery Cycle count total 275 * Return the battery Cycle count total
225 * Or < 0 if something fails. 276 * Or < 0 if something fails.
226 */ 277 */
@@ -245,7 +296,8 @@ static int bq27x00_battery_read_time(struct bq27x00_device_info *di, u8 reg)
245 296
246 tval = bq27x00_read(di, reg, false); 297 tval = bq27x00_read(di, reg, false);
247 if (tval < 0) { 298 if (tval < 0) {
248 dev_err(di->dev, "error reading register %02x: %d\n", reg, tval); 299 dev_dbg(di->dev, "error reading time register %02x: %d\n",
300 reg, tval);
249 return tval; 301 return tval;
250 } 302 }
251 303
@@ -262,25 +314,31 @@ static void bq27x00_update(struct bq27x00_device_info *di)
262 314
263 cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, is_bq27500); 315 cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, is_bq27500);
264 if (cache.flags >= 0) { 316 if (cache.flags >= 0) {
265 cache.capacity = bq27x00_battery_read_rsoc(di); 317 if (!is_bq27500 && (cache.flags & BQ27000_FLAG_CI)) {
266 cache.temperature = bq27x00_read(di, BQ27x00_REG_TEMP, false); 318 dev_info(di->dev, "battery is not calibrated! ignoring capacity values\n");
267 cache.time_to_empty = bq27x00_battery_read_time(di, BQ27x00_REG_TTE); 319 cache.capacity = -ENODATA;
268 cache.time_to_empty_avg = bq27x00_battery_read_time(di, BQ27x00_REG_TTECP); 320 cache.energy = -ENODATA;
269 cache.time_to_full = bq27x00_battery_read_time(di, BQ27x00_REG_TTF); 321 cache.time_to_empty = -ENODATA;
270 cache.charge_full = bq27x00_battery_read_lmd(di); 322 cache.time_to_empty_avg = -ENODATA;
323 cache.time_to_full = -ENODATA;
324 cache.charge_full = -ENODATA;
325 } else {
326 cache.capacity = bq27x00_battery_read_rsoc(di);
327 cache.energy = bq27x00_battery_read_energy(di);
328 cache.time_to_empty = bq27x00_battery_read_time(di, BQ27x00_REG_TTE);
329 cache.time_to_empty_avg = bq27x00_battery_read_time(di, BQ27x00_REG_TTECP);
330 cache.time_to_full = bq27x00_battery_read_time(di, BQ27x00_REG_TTF);
331 cache.charge_full = bq27x00_battery_read_lmd(di);
332 }
333 cache.temperature = bq27x00_battery_read_temperature(di);
271 cache.cycle_count = bq27x00_battery_read_cyct(di); 334 cache.cycle_count = bq27x00_battery_read_cyct(di);
272 335
273 if (!is_bq27500)
274 cache.current_now = bq27x00_read(di, BQ27x00_REG_AI, false);
275
276 /* We only have to read charge design full once */ 336 /* We only have to read charge design full once */
277 if (di->charge_design_full <= 0) 337 if (di->charge_design_full <= 0)
278 di->charge_design_full = bq27x00_battery_read_ilmd(di); 338 di->charge_design_full = bq27x00_battery_read_ilmd(di);
279 } 339 }
280 340
281 /* Ignore current_now which is a snapshot of the current battery state 341 if (memcmp(&di->cache, &cache, sizeof(cache)) != 0) {
282 * and is likely to be different even between two consecutive reads */
283 if (memcmp(&di->cache, &cache, sizeof(cache) - sizeof(int)) != 0) {
284 di->cache = cache; 342 di->cache = cache;
285 power_supply_changed(&di->bat); 343 power_supply_changed(&di->bat);
286 } 344 }
@@ -302,25 +360,6 @@ static void bq27x00_battery_poll(struct work_struct *work)
302 } 360 }
303} 361}
304 362
305
306/*
307 * Return the battery temperature in tenths of degree Celsius
308 * Or < 0 if something fails.
309 */
310static int bq27x00_battery_temperature(struct bq27x00_device_info *di,
311 union power_supply_propval *val)
312{
313 if (di->cache.temperature < 0)
314 return di->cache.temperature;
315
316 if (di->chip == BQ27500)
317 val->intval = di->cache.temperature - 2731;
318 else
319 val->intval = ((di->cache.temperature * 5) - 5463) / 2;
320
321 return 0;
322}
323
324/* 363/*
325 * Return the battery average current in µA 364 * Return the battery average current in µA
326 * Note that current can be negative signed as well 365 * Note that current can be negative signed as well
@@ -330,20 +369,20 @@ static int bq27x00_battery_current(struct bq27x00_device_info *di,
330 union power_supply_propval *val) 369 union power_supply_propval *val)
331{ 370{
332 int curr; 371 int curr;
372 int flags;
333 373
334 if (di->chip == BQ27500) 374 curr = bq27x00_read(di, BQ27x00_REG_AI, false);
335 curr = bq27x00_read(di, BQ27x00_REG_AI, false); 375 if (curr < 0) {
336 else 376 dev_err(di->dev, "error reading current\n");
337 curr = di->cache.current_now;
338
339 if (curr < 0)
340 return curr; 377 return curr;
378 }
341 379
342 if (di->chip == BQ27500) { 380 if (di->chip == BQ27500) {
343 /* bq27500 returns signed value */ 381 /* bq27500 returns signed value */
344 val->intval = (int)((s16)curr) * 1000; 382 val->intval = (int)((s16)curr) * 1000;
345 } else { 383 } else {
346 if (di->cache.flags & BQ27000_FLAG_CHGS) { 384 flags = bq27x00_read(di, BQ27x00_REG_FLAGS, false);
385 if (flags & BQ27000_FLAG_CHGS) {
347 dev_dbg(di->dev, "negative current!\n"); 386 dev_dbg(di->dev, "negative current!\n");
348 curr = -curr; 387 curr = -curr;
349 } 388 }
@@ -362,10 +401,14 @@ static int bq27x00_battery_status(struct bq27x00_device_info *di,
362 if (di->chip == BQ27500) { 401 if (di->chip == BQ27500) {
363 if (di->cache.flags & BQ27500_FLAG_FC) 402 if (di->cache.flags & BQ27500_FLAG_FC)
364 status = POWER_SUPPLY_STATUS_FULL; 403 status = POWER_SUPPLY_STATUS_FULL;
365 else if (di->cache.flags & BQ27500_FLAG_DSC) 404 else if (di->cache.flags & BQ27500_FLAG_DSG)
366 status = POWER_SUPPLY_STATUS_DISCHARGING; 405 status = POWER_SUPPLY_STATUS_DISCHARGING;
367 else 406 else if (di->cache.flags & BQ27500_FLAG_CHG)
368 status = POWER_SUPPLY_STATUS_CHARGING; 407 status = POWER_SUPPLY_STATUS_CHARGING;
408 else if (power_supply_am_i_supplied(&di->bat))
409 status = POWER_SUPPLY_STATUS_NOT_CHARGING;
410 else
411 status = POWER_SUPPLY_STATUS_UNKNOWN;
369 } else { 412 } else {
370 if (di->cache.flags & BQ27000_FLAG_FC) 413 if (di->cache.flags & BQ27000_FLAG_FC)
371 status = POWER_SUPPLY_STATUS_FULL; 414 status = POWER_SUPPLY_STATUS_FULL;
@@ -382,50 +425,56 @@ static int bq27x00_battery_status(struct bq27x00_device_info *di,
382 return 0; 425 return 0;
383} 426}
384 427
385/* 428static int bq27x00_battery_capacity_level(struct bq27x00_device_info *di,
386 * Return the battery Voltage in milivolts
387 * Or < 0 if something fails.
388 */
389static int bq27x00_battery_voltage(struct bq27x00_device_info *di,
390 union power_supply_propval *val) 429 union power_supply_propval *val)
391{ 430{
392 int volt; 431 int level;
393 432
394 volt = bq27x00_read(di, BQ27x00_REG_VOLT, false); 433 if (di->chip == BQ27500) {
395 if (volt < 0) 434 if (di->cache.flags & BQ27500_FLAG_FC)
396 return volt; 435 level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
436 else if (di->cache.flags & BQ27500_FLAG_SOC1)
437 level = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
438 else if (di->cache.flags & BQ27500_FLAG_SOCF)
439 level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
440 else
441 level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
442 } else {
443 if (di->cache.flags & BQ27000_FLAG_FC)
444 level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
445 else if (di->cache.flags & BQ27000_FLAG_EDV1)
446 level = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
447 else if (di->cache.flags & BQ27000_FLAG_EDVF)
448 level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
449 else
450 level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
451 }
397 452
398 val->intval = volt * 1000; 453 val->intval = level;
399 454
400 return 0; 455 return 0;
401} 456}
402 457
403/* 458/*
404 * Return the battery Available energy in µWh 459 * Return the battery Voltage in milivolts
405 * Or < 0 if something fails. 460 * Or < 0 if something fails.
406 */ 461 */
407static int bq27x00_battery_energy(struct bq27x00_device_info *di, 462static int bq27x00_battery_voltage(struct bq27x00_device_info *di,
408 union power_supply_propval *val) 463 union power_supply_propval *val)
409{ 464{
410 int ae; 465 int volt;
411 466
412 ae = bq27x00_read(di, BQ27x00_REG_AE, false); 467 volt = bq27x00_read(di, BQ27x00_REG_VOLT, false);
413 if (ae < 0) { 468 if (volt < 0) {
414 dev_err(di->dev, "error reading available energy\n"); 469 dev_err(di->dev, "error reading voltage\n");
415 return ae; 470 return volt;
416 } 471 }
417 472
418 if (di->chip == BQ27500) 473 val->intval = volt * 1000;
419 ae *= 1000;
420 else
421 ae = ae * 29200 / BQ27000_RS;
422
423 val->intval = ae;
424 474
425 return 0; 475 return 0;
426} 476}
427 477
428
429static int bq27x00_simple_value(int value, 478static int bq27x00_simple_value(int value,
430 union power_supply_propval *val) 479 union power_supply_propval *val)
431{ 480{
@@ -473,8 +522,11 @@ static int bq27x00_battery_get_property(struct power_supply *psy,
473 case POWER_SUPPLY_PROP_CAPACITY: 522 case POWER_SUPPLY_PROP_CAPACITY:
474 ret = bq27x00_simple_value(di->cache.capacity, val); 523 ret = bq27x00_simple_value(di->cache.capacity, val);
475 break; 524 break;
525 case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
526 ret = bq27x00_battery_capacity_level(di, val);
527 break;
476 case POWER_SUPPLY_PROP_TEMP: 528 case POWER_SUPPLY_PROP_TEMP:
477 ret = bq27x00_battery_temperature(di, val); 529 ret = bq27x00_simple_value(di->cache.temperature, val);
478 break; 530 break;
479 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW: 531 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
480 ret = bq27x00_simple_value(di->cache.time_to_empty, val); 532 ret = bq27x00_simple_value(di->cache.time_to_empty, val);
@@ -501,7 +553,7 @@ static int bq27x00_battery_get_property(struct power_supply *psy,
501 ret = bq27x00_simple_value(di->cache.cycle_count, val); 553 ret = bq27x00_simple_value(di->cache.cycle_count, val);
502 break; 554 break;
503 case POWER_SUPPLY_PROP_ENERGY_NOW: 555 case POWER_SUPPLY_PROP_ENERGY_NOW:
504 ret = bq27x00_battery_energy(di, val); 556 ret = bq27x00_simple_value(di->cache.energy, val);
505 break; 557 break;
506 default: 558 default:
507 return -EINVAL; 559 return -EINVAL;
@@ -546,6 +598,14 @@ static int bq27x00_powersupply_init(struct bq27x00_device_info *di)
546 598
547static void bq27x00_powersupply_unregister(struct bq27x00_device_info *di) 599static void bq27x00_powersupply_unregister(struct bq27x00_device_info *di)
548{ 600{
601 /*
602 * power_supply_unregister call bq27x00_battery_get_property which
603 * call bq27x00_battery_poll.
604 * Make sure that bq27x00_battery_poll will not call
605 * schedule_delayed_work again after unregister (which cause OOPS).
606 */
607 poll_interval = 0;
608
549 cancel_delayed_work_sync(&di->work); 609 cancel_delayed_work_sync(&di->work);
550 610
551 power_supply_unregister(&di->bat); 611 power_supply_unregister(&di->bat);
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
new file mode 100644
index 00000000000..0378d019efa
--- /dev/null
+++ b/drivers/power/charger-manager.c
@@ -0,0 +1,1072 @@
1/*
2 * Copyright (C) 2011 Samsung Electronics Co., Ltd.
3 * MyungJoo Ham <myungjoo.ham@samsung.com>
4 *
5 * This driver enables to monitor battery health and control charger
6 * during suspend-to-mem.
7 * Charger manager depends on other devices. register this later than
8 * the depending devices.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13**/
14
15#include <linux/io.h>
16#include <linux/module.h>
17#include <linux/irq.h>
18#include <linux/interrupt.h>
19#include <linux/rtc.h>
20#include <linux/slab.h>
21#include <linux/workqueue.h>
22#include <linux/platform_device.h>
23#include <linux/power/charger-manager.h>
24#include <linux/regulator/consumer.h>
25
26/*
27 * Regard CM_JIFFIES_SMALL jiffies is small enough to ignore for
28 * delayed works so that we can run delayed works with CM_JIFFIES_SMALL
29 * without any delays.
30 */
31#define CM_JIFFIES_SMALL (2)
32
33/* If y is valid (> 0) and smaller than x, do x = y */
34#define CM_MIN_VALID(x, y) x = (((y > 0) && ((x) > (y))) ? (y) : (x))
35
36/*
37 * Regard CM_RTC_SMALL (sec) is small enough to ignore error in invoking
38 * rtc alarm. It should be 2 or larger
39 */
40#define CM_RTC_SMALL (2)
41
42#define UEVENT_BUF_SIZE 32
43
44static LIST_HEAD(cm_list);
45static DEFINE_MUTEX(cm_list_mtx);
46
47/* About in-suspend (suspend-again) monitoring */
48static struct rtc_device *rtc_dev;
49/*
50 * Backup RTC alarm
51 * Save the wakeup alarm before entering suspend-to-RAM
52 */
53static struct rtc_wkalrm rtc_wkalarm_save;
54/* Backup RTC alarm time in terms of seconds since 01-01-1970 00:00:00 */
55static unsigned long rtc_wkalarm_save_time;
56static bool cm_suspended;
57static bool cm_rtc_set;
58static unsigned long cm_suspend_duration_ms;
59
60/* Global charger-manager description */
61static struct charger_global_desc *g_desc; /* init with setup_charger_manager */
62
63/**
64 * is_batt_present - See if the battery presents in place.
65 * @cm: the Charger Manager representing the battery.
66 */
67static bool is_batt_present(struct charger_manager *cm)
68{
69 union power_supply_propval val;
70 bool present = false;
71 int i, ret;
72
73 switch (cm->desc->battery_present) {
74 case CM_FUEL_GAUGE:
75 ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
76 POWER_SUPPLY_PROP_PRESENT, &val);
77 if (ret == 0 && val.intval)
78 present = true;
79 break;
80 case CM_CHARGER_STAT:
81 for (i = 0; cm->charger_stat[i]; i++) {
82 ret = cm->charger_stat[i]->get_property(
83 cm->charger_stat[i],
84 POWER_SUPPLY_PROP_PRESENT, &val);
85 if (ret == 0 && val.intval) {
86 present = true;
87 break;
88 }
89 }
90 break;
91 }
92
93 return present;
94}
95
96/**
97 * is_ext_pwr_online - See if an external power source is attached to charge
98 * @cm: the Charger Manager representing the battery.
99 *
100 * Returns true if at least one of the chargers of the battery has an external
101 * power source attached to charge the battery regardless of whether it is
102 * actually charging or not.
103 */
104static bool is_ext_pwr_online(struct charger_manager *cm)
105{
106 union power_supply_propval val;
107 bool online = false;
108 int i, ret;
109
110 /* If at least one of them has one, it's yes. */
111 for (i = 0; cm->charger_stat[i]; i++) {
112 ret = cm->charger_stat[i]->get_property(
113 cm->charger_stat[i],
114 POWER_SUPPLY_PROP_ONLINE, &val);
115 if (ret == 0 && val.intval) {
116 online = true;
117 break;
118 }
119 }
120
121 return online;
122}
123
124/**
125 * get_batt_uV - Get the voltage level of the battery
126 * @cm: the Charger Manager representing the battery.
127 * @uV: the voltage level returned.
128 *
129 * Returns 0 if there is no error.
130 * Returns a negative value on error.
131 */
132static int get_batt_uV(struct charger_manager *cm, int *uV)
133{
134 union power_supply_propval val;
135 int ret;
136
137 if (cm->fuel_gauge)
138 ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
139 POWER_SUPPLY_PROP_VOLTAGE_NOW, &val);
140 else
141 return -ENODEV;
142
143 if (ret)
144 return ret;
145
146 *uV = val.intval;
147 return 0;
148}
149
150/**
151 * is_charging - Returns true if the battery is being charged.
152 * @cm: the Charger Manager representing the battery.
153 */
154static bool is_charging(struct charger_manager *cm)
155{
156 int i, ret;
157 bool charging = false;
158 union power_supply_propval val;
159
160 /* If there is no battery, it cannot be charged */
161 if (!is_batt_present(cm))
162 return false;
163
164 /* If at least one of the charger is charging, return yes */
165 for (i = 0; cm->charger_stat[i]; i++) {
166 /* 1. The charger sholuld not be DISABLED */
167 if (cm->emergency_stop)
168 continue;
169 if (!cm->charger_enabled)
170 continue;
171
172 /* 2. The charger should be online (ext-power) */
173 ret = cm->charger_stat[i]->get_property(
174 cm->charger_stat[i],
175 POWER_SUPPLY_PROP_ONLINE, &val);
176 if (ret) {
177 dev_warn(cm->dev, "Cannot read ONLINE value from %s.\n",
178 cm->desc->psy_charger_stat[i]);
179 continue;
180 }
181 if (val.intval == 0)
182 continue;
183
184 /*
185 * 3. The charger should not be FULL, DISCHARGING,
186 * or NOT_CHARGING.
187 */
188 ret = cm->charger_stat[i]->get_property(
189 cm->charger_stat[i],
190 POWER_SUPPLY_PROP_STATUS, &val);
191 if (ret) {
192 dev_warn(cm->dev, "Cannot read STATUS value from %s.\n",
193 cm->desc->psy_charger_stat[i]);
194 continue;
195 }
196 if (val.intval == POWER_SUPPLY_STATUS_FULL ||
197 val.intval == POWER_SUPPLY_STATUS_DISCHARGING ||
198 val.intval == POWER_SUPPLY_STATUS_NOT_CHARGING)
199 continue;
200
201 /* Then, this is charging. */
202 charging = true;
203 break;
204 }
205
206 return charging;
207}
208
209/**
210 * is_polling_required - Return true if need to continue polling for this CM.
211 * @cm: the Charger Manager representing the battery.
212 */
213static bool is_polling_required(struct charger_manager *cm)
214{
215 switch (cm->desc->polling_mode) {
216 case CM_POLL_DISABLE:
217 return false;
218 case CM_POLL_ALWAYS:
219 return true;
220 case CM_POLL_EXTERNAL_POWER_ONLY:
221 return is_ext_pwr_online(cm);
222 case CM_POLL_CHARGING_ONLY:
223 return is_charging(cm);
224 default:
225 dev_warn(cm->dev, "Incorrect polling_mode (%d)\n",
226 cm->desc->polling_mode);
227 }
228
229 return false;
230}
231
232/**
233 * try_charger_enable - Enable/Disable chargers altogether
234 * @cm: the Charger Manager representing the battery.
235 * @enable: true: enable / false: disable
236 *
237 * Note that Charger Manager keeps the charger enabled regardless whether
238 * the charger is charging or not (because battery is full or no external
239 * power source exists) except when CM needs to disable chargers forcibly
240 * bacause of emergency causes; when the battery is overheated or too cold.
241 */
242static int try_charger_enable(struct charger_manager *cm, bool enable)
243{
244 int err = 0, i;
245 struct charger_desc *desc = cm->desc;
246
247 /* Ignore if it's redundent command */
248 if (enable && cm->charger_enabled)
249 return 0;
250 if (!enable && !cm->charger_enabled)
251 return 0;
252
253 if (enable) {
254 if (cm->emergency_stop)
255 return -EAGAIN;
256 err = regulator_bulk_enable(desc->num_charger_regulators,
257 desc->charger_regulators);
258 } else {
259 /*
260 * Abnormal battery state - Stop charging forcibly,
261 * even if charger was enabled at the other places
262 */
263 err = regulator_bulk_disable(desc->num_charger_regulators,
264 desc->charger_regulators);
265
266 for (i = 0; i < desc->num_charger_regulators; i++) {
267 if (regulator_is_enabled(
268 desc->charger_regulators[i].consumer)) {
269 regulator_force_disable(
270 desc->charger_regulators[i].consumer);
271 dev_warn(cm->dev,
272 "Disable regulator(%s) forcibly.\n",
273 desc->charger_regulators[i].supply);
274 }
275 }
276 }
277
278 if (!err)
279 cm->charger_enabled = enable;
280
281 return err;
282}
283
284/**
285 * uevent_notify - Let users know something has changed.
286 * @cm: the Charger Manager representing the battery.
287 * @event: the event string.
288 *
289 * If @event is null, it implies that uevent_notify is called
290 * by resume function. When called in the resume function, cm_suspended
291 * should be already reset to false in order to let uevent_notify
292 * notify the recent event during the suspend to users. While
293 * suspended, uevent_notify does not notify users, but tracks
294 * events so that uevent_notify can notify users later after resumed.
295 */
296static void uevent_notify(struct charger_manager *cm, const char *event)
297{
298 static char env_str[UEVENT_BUF_SIZE + 1] = "";
299 static char env_str_save[UEVENT_BUF_SIZE + 1] = "";
300
301 if (cm_suspended) {
302 /* Nothing in suspended-event buffer */
303 if (env_str_save[0] == 0) {
304 if (!strncmp(env_str, event, UEVENT_BUF_SIZE))
305 return; /* status not changed */
306 strncpy(env_str_save, event, UEVENT_BUF_SIZE);
307 return;
308 }
309
310 if (!strncmp(env_str_save, event, UEVENT_BUF_SIZE))
311 return; /* Duplicated. */
312 else
313 strncpy(env_str_save, event, UEVENT_BUF_SIZE);
314
315 return;
316 }
317
318 if (event == NULL) {
319 /* No messages pending */
320 if (!env_str_save[0])
321 return;
322
323 strncpy(env_str, env_str_save, UEVENT_BUF_SIZE);
324 kobject_uevent(&cm->dev->kobj, KOBJ_CHANGE);
325 env_str_save[0] = 0;
326
327 return;
328 }
329
330 /* status not changed */
331 if (!strncmp(env_str, event, UEVENT_BUF_SIZE))
332 return;
333
334 /* save the status and notify the update */
335 strncpy(env_str, event, UEVENT_BUF_SIZE);
336 kobject_uevent(&cm->dev->kobj, KOBJ_CHANGE);
337
338 dev_info(cm->dev, event);
339}
340
341/**
342 * _cm_monitor - Monitor the temperature and return true for exceptions.
343 * @cm: the Charger Manager representing the battery.
344 *
345 * Returns true if there is an event to notify for the battery.
346 * (True if the status of "emergency_stop" changes)
347 */
348static bool _cm_monitor(struct charger_manager *cm)
349{
350 struct charger_desc *desc = cm->desc;
351 int temp = desc->temperature_out_of_range(&cm->last_temp_mC);
352
353 dev_dbg(cm->dev, "monitoring (%2.2d.%3.3dC)\n",
354 cm->last_temp_mC / 1000, cm->last_temp_mC % 1000);
355
356 /* It has been stopped or charging already */
357 if (!!temp == !!cm->emergency_stop)
358 return false;
359
360 if (temp) {
361 cm->emergency_stop = temp;
362 if (!try_charger_enable(cm, false)) {
363 if (temp > 0)
364 uevent_notify(cm, "OVERHEAT");
365 else
366 uevent_notify(cm, "COLD");
367 }
368 } else {
369 cm->emergency_stop = 0;
370 if (!try_charger_enable(cm, true))
371 uevent_notify(cm, "CHARGING");
372 }
373
374 return true;
375}
376
377/**
378 * cm_monitor - Monitor every battery.
379 *
380 * Returns true if there is an event to notify from any of the batteries.
381 * (True if the status of "emergency_stop" changes)
382 */
383static bool cm_monitor(void)
384{
385 bool stop = false;
386 struct charger_manager *cm;
387
388 mutex_lock(&cm_list_mtx);
389
390 list_for_each_entry(cm, &cm_list, entry)
391 stop = stop || _cm_monitor(cm);
392
393 mutex_unlock(&cm_list_mtx);
394
395 return stop;
396}
397
398static int charger_get_property(struct power_supply *psy,
399 enum power_supply_property psp,
400 union power_supply_propval *val)
401{
402 struct charger_manager *cm = container_of(psy,
403 struct charger_manager, charger_psy);
404 struct charger_desc *desc = cm->desc;
405 int i, ret = 0, uV;
406
407 switch (psp) {
408 case POWER_SUPPLY_PROP_STATUS:
409 if (is_charging(cm))
410 val->intval = POWER_SUPPLY_STATUS_CHARGING;
411 else if (is_ext_pwr_online(cm))
412 val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
413 else
414 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
415 break;
416 case POWER_SUPPLY_PROP_HEALTH:
417 if (cm->emergency_stop > 0)
418 val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
419 else if (cm->emergency_stop < 0)
420 val->intval = POWER_SUPPLY_HEALTH_COLD;
421 else
422 val->intval = POWER_SUPPLY_HEALTH_GOOD;
423 break;
424 case POWER_SUPPLY_PROP_PRESENT:
425 if (is_batt_present(cm))
426 val->intval = 1;
427 else
428 val->intval = 0;
429 break;
430 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
431 ret = get_batt_uV(cm, &i);
432 val->intval = i;
433 break;
434 case POWER_SUPPLY_PROP_CURRENT_NOW:
435 ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
436 POWER_SUPPLY_PROP_CURRENT_NOW, val);
437 break;
438 case POWER_SUPPLY_PROP_TEMP:
439 /* in thenth of centigrade */
440 if (cm->last_temp_mC == INT_MIN)
441 desc->temperature_out_of_range(&cm->last_temp_mC);
442 val->intval = cm->last_temp_mC / 100;
443 if (!desc->measure_battery_temp)
444 ret = -ENODEV;
445 break;
446 case POWER_SUPPLY_PROP_TEMP_AMBIENT:
447 /* in thenth of centigrade */
448 if (cm->last_temp_mC == INT_MIN)
449 desc->temperature_out_of_range(&cm->last_temp_mC);
450 val->intval = cm->last_temp_mC / 100;
451 if (desc->measure_battery_temp)
452 ret = -ENODEV;
453 break;
454 case POWER_SUPPLY_PROP_CAPACITY:
455 if (!cm->fuel_gauge) {
456 ret = -ENODEV;
457 break;
458 }
459
460 if (!is_batt_present(cm)) {
461 /* There is no battery. Assume 100% */
462 val->intval = 100;
463 break;
464 }
465
466 ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
467 POWER_SUPPLY_PROP_CAPACITY, val);
468 if (ret)
469 break;
470
471 if (val->intval > 100) {
472 val->intval = 100;
473 break;
474 }
475 if (val->intval < 0)
476 val->intval = 0;
477
478 /* Do not adjust SOC when charging: voltage is overrated */
479 if (is_charging(cm))
480 break;
481
482 /*
483 * If the capacity value is inconsistent, calibrate it base on
484 * the battery voltage values and the thresholds given as desc
485 */
486 ret = get_batt_uV(cm, &uV);
487 if (ret) {
488 /* Voltage information not available. No calibration */
489 ret = 0;
490 break;
491 }
492
493 if (desc->fullbatt_uV > 0 && uV >= desc->fullbatt_uV &&
494 !is_charging(cm)) {
495 val->intval = 100;
496 break;
497 }
498
499 break;
500 case POWER_SUPPLY_PROP_ONLINE:
501 if (is_ext_pwr_online(cm))
502 val->intval = 1;
503 else
504 val->intval = 0;
505 break;
506 case POWER_SUPPLY_PROP_CHARGE_FULL:
507 if (cm->fuel_gauge) {
508 if (cm->fuel_gauge->get_property(cm->fuel_gauge,
509 POWER_SUPPLY_PROP_CHARGE_FULL, val) == 0)
510 break;
511 }
512
513 if (is_ext_pwr_online(cm)) {
514 /* Not full if it's charging. */
515 if (is_charging(cm)) {
516 val->intval = 0;
517 break;
518 }
519 /*
520 * Full if it's powered but not charging andi
521 * not forced stop by emergency
522 */
523 if (!cm->emergency_stop) {
524 val->intval = 1;
525 break;
526 }
527 }
528
529 /* Full if it's over the fullbatt voltage */
530 ret = get_batt_uV(cm, &uV);
531 if (!ret && desc->fullbatt_uV > 0 && uV >= desc->fullbatt_uV &&
532 !is_charging(cm)) {
533 val->intval = 1;
534 break;
535 }
536
537 /* Full if the cap is 100 */
538 if (cm->fuel_gauge) {
539 ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
540 POWER_SUPPLY_PROP_CAPACITY, val);
541 if (!ret && val->intval >= 100 && !is_charging(cm)) {
542 val->intval = 1;
543 break;
544 }
545 }
546
547 val->intval = 0;
548 ret = 0;
549 break;
550 case POWER_SUPPLY_PROP_CHARGE_NOW:
551 if (is_charging(cm)) {
552 ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
553 POWER_SUPPLY_PROP_CHARGE_NOW,
554 val);
555 if (ret) {
556 val->intval = 1;
557 ret = 0;
558 } else {
559 /* If CHARGE_NOW is supplied, use it */
560 val->intval = (val->intval > 0) ?
561 val->intval : 1;
562 }
563 } else {
564 val->intval = 0;
565 }
566 break;
567 default:
568 return -EINVAL;
569 }
570 return ret;
571}
572
573#define NUM_CHARGER_PSY_OPTIONAL (4)
574static enum power_supply_property default_charger_props[] = {
575 /* Guaranteed to provide */
576 POWER_SUPPLY_PROP_STATUS,
577 POWER_SUPPLY_PROP_HEALTH,
578 POWER_SUPPLY_PROP_PRESENT,
579 POWER_SUPPLY_PROP_VOLTAGE_NOW,
580 POWER_SUPPLY_PROP_CAPACITY,
581 POWER_SUPPLY_PROP_ONLINE,
582 POWER_SUPPLY_PROP_CHARGE_FULL,
583 /*
584 * Optional properties are:
585 * POWER_SUPPLY_PROP_CHARGE_NOW,
586 * POWER_SUPPLY_PROP_CURRENT_NOW,
587 * POWER_SUPPLY_PROP_TEMP, and
588 * POWER_SUPPLY_PROP_TEMP_AMBIENT,
589 */
590};
591
592static struct power_supply psy_default = {
593 .name = "battery",
594 .type = POWER_SUPPLY_TYPE_BATTERY,
595 .properties = default_charger_props,
596 .num_properties = ARRAY_SIZE(default_charger_props),
597 .get_property = charger_get_property,
598};
599
600/**
601 * cm_setup_timer - For in-suspend monitoring setup wakeup alarm
602 * for suspend_again.
603 *
604 * Returns true if the alarm is set for Charger Manager to use.
605 * Returns false if
606 * cm_setup_timer fails to set an alarm,
607 * cm_setup_timer does not need to set an alarm for Charger Manager,
608 * or an alarm previously configured is to be used.
609 */
610static bool cm_setup_timer(void)
611{
612 struct charger_manager *cm;
613 unsigned int wakeup_ms = UINT_MAX;
614 bool ret = false;
615
616 mutex_lock(&cm_list_mtx);
617
618 list_for_each_entry(cm, &cm_list, entry) {
619 /* Skip if polling is not required for this CM */
620 if (!is_polling_required(cm) && !cm->emergency_stop)
621 continue;
622 if (cm->desc->polling_interval_ms == 0)
623 continue;
624 CM_MIN_VALID(wakeup_ms, cm->desc->polling_interval_ms);
625 }
626
627 mutex_unlock(&cm_list_mtx);
628
629 if (wakeup_ms < UINT_MAX && wakeup_ms > 0) {
630 pr_info("Charger Manager wakeup timer: %u ms.\n", wakeup_ms);
631 if (rtc_dev) {
632 struct rtc_wkalrm tmp;
633 unsigned long time, now;
634 unsigned long add = DIV_ROUND_UP(wakeup_ms, 1000);
635
636 /*
637 * Set alarm with the polling interval (wakeup_ms)
638 * except when rtc_wkalarm_save comes first.
639 * However, the alarm time should be NOW +
640 * CM_RTC_SMALL or later.
641 */
642 tmp.enabled = 1;
643 rtc_read_time(rtc_dev, &tmp.time);
644 rtc_tm_to_time(&tmp.time, &now);
645 if (add < CM_RTC_SMALL)
646 add = CM_RTC_SMALL;
647 time = now + add;
648
649 ret = true;
650
651 if (rtc_wkalarm_save.enabled &&
652 rtc_wkalarm_save_time &&
653 rtc_wkalarm_save_time < time) {
654 if (rtc_wkalarm_save_time < now + CM_RTC_SMALL)
655 time = now + CM_RTC_SMALL;
656 else
657 time = rtc_wkalarm_save_time;
658
659 /* The timer is not appointed by CM */
660 ret = false;
661 }
662
663 pr_info("Waking up after %lu secs.\n",
664 time - now);
665
666 rtc_time_to_tm(time, &tmp.time);
667 rtc_set_alarm(rtc_dev, &tmp);
668 cm_suspend_duration_ms += wakeup_ms;
669 return ret;
670 }
671 }
672
673 if (rtc_dev)
674 rtc_set_alarm(rtc_dev, &rtc_wkalarm_save);
675 return false;
676}
677
678/**
679 * cm_suspend_again - Determine whether suspend again or not
680 *
681 * Returns true if the system should be suspended again
682 * Returns false if the system should be woken up
683 */
684bool cm_suspend_again(void)
685{
686 struct charger_manager *cm;
687 bool ret = false;
688
689 if (!g_desc || !g_desc->rtc_only_wakeup || !g_desc->rtc_only_wakeup() ||
690 !cm_rtc_set)
691 return false;
692
693 if (cm_monitor())
694 goto out;
695
696 ret = true;
697 mutex_lock(&cm_list_mtx);
698 list_for_each_entry(cm, &cm_list, entry) {
699 if (cm->status_save_ext_pwr_inserted != is_ext_pwr_online(cm) ||
700 cm->status_save_batt != is_batt_present(cm))
701 ret = false;
702 }
703 mutex_unlock(&cm_list_mtx);
704
705 cm_rtc_set = cm_setup_timer();
706out:
707 /* It's about the time when the non-CM appointed timer goes off */
708 if (rtc_wkalarm_save.enabled) {
709 unsigned long now;
710 struct rtc_time tmp;
711
712 rtc_read_time(rtc_dev, &tmp);
713 rtc_tm_to_time(&tmp, &now);
714
715 if (rtc_wkalarm_save_time &&
716 now + CM_RTC_SMALL >= rtc_wkalarm_save_time)
717 return false;
718 }
719 return ret;
720}
721EXPORT_SYMBOL_GPL(cm_suspend_again);
722
723/**
724 * setup_charger_manager - initialize charger_global_desc data
725 * @gd: pointer to instance of charger_global_desc
726 */
727int setup_charger_manager(struct charger_global_desc *gd)
728{
729 if (!gd)
730 return -EINVAL;
731
732 if (rtc_dev)
733 rtc_class_close(rtc_dev);
734 rtc_dev = NULL;
735 g_desc = NULL;
736
737 if (!gd->rtc_only_wakeup) {
738 pr_err("The callback rtc_only_wakeup is not given.\n");
739 return -EINVAL;
740 }
741
742 if (gd->rtc_name) {
743 rtc_dev = rtc_class_open(gd->rtc_name);
744 if (IS_ERR_OR_NULL(rtc_dev)) {
745 rtc_dev = NULL;
746 /* Retry at probe. RTC may be not registered yet */
747 }
748 } else {
749 pr_warn("No wakeup timer is given for charger manager."
750 "In-suspend monitoring won't work.\n");
751 }
752
753 g_desc = gd;
754 return 0;
755}
756EXPORT_SYMBOL_GPL(setup_charger_manager);
757
758static int charger_manager_probe(struct platform_device *pdev)
759{
760 struct charger_desc *desc = dev_get_platdata(&pdev->dev);
761 struct charger_manager *cm;
762 int ret = 0, i = 0;
763 union power_supply_propval val;
764
765 if (g_desc && !rtc_dev && g_desc->rtc_name) {
766 rtc_dev = rtc_class_open(g_desc->rtc_name);
767 if (IS_ERR_OR_NULL(rtc_dev)) {
768 rtc_dev = NULL;
769 dev_err(&pdev->dev, "Cannot get RTC %s.\n",
770 g_desc->rtc_name);
771 ret = -ENODEV;
772 goto err_alloc;
773 }
774 }
775
776 if (!desc) {
777 dev_err(&pdev->dev, "No platform data (desc) found.\n");
778 ret = -ENODEV;
779 goto err_alloc;
780 }
781
782 cm = kzalloc(sizeof(struct charger_manager), GFP_KERNEL);
783 if (!cm) {
784 dev_err(&pdev->dev, "Cannot allocate memory.\n");
785 ret = -ENOMEM;
786 goto err_alloc;
787 }
788
789 /* Basic Values. Unspecified are Null or 0 */
790 cm->dev = &pdev->dev;
791 cm->desc = kzalloc(sizeof(struct charger_desc), GFP_KERNEL);
792 if (!cm->desc) {
793 dev_err(&pdev->dev, "Cannot allocate memory.\n");
794 ret = -ENOMEM;
795 goto err_alloc_desc;
796 }
797 memcpy(cm->desc, desc, sizeof(struct charger_desc));
798 cm->last_temp_mC = INT_MIN; /* denotes "unmeasured, yet" */
799
800 if (!desc->charger_regulators || desc->num_charger_regulators < 1) {
801 ret = -EINVAL;
802 dev_err(&pdev->dev, "charger_regulators undefined.\n");
803 goto err_no_charger;
804 }
805
806 if (!desc->psy_charger_stat || !desc->psy_charger_stat[0]) {
807 dev_err(&pdev->dev, "No power supply defined.\n");
808 ret = -EINVAL;
809 goto err_no_charger_stat;
810 }
811
812 /* Counting index only */
813 while (desc->psy_charger_stat[i])
814 i++;
815
816 cm->charger_stat = kzalloc(sizeof(struct power_supply *) * (i + 1),
817 GFP_KERNEL);
818 if (!cm->charger_stat) {
819 ret = -ENOMEM;
820 goto err_no_charger_stat;
821 }
822
823 for (i = 0; desc->psy_charger_stat[i]; i++) {
824 cm->charger_stat[i] = power_supply_get_by_name(
825 desc->psy_charger_stat[i]);
826 if (!cm->charger_stat[i]) {
827 dev_err(&pdev->dev, "Cannot find power supply "
828 "\"%s\"\n",
829 desc->psy_charger_stat[i]);
830 ret = -ENODEV;
831 goto err_chg_stat;
832 }
833 }
834
835 cm->fuel_gauge = power_supply_get_by_name(desc->psy_fuel_gauge);
836 if (!cm->fuel_gauge) {
837 dev_err(&pdev->dev, "Cannot find power supply \"%s\"\n",
838 desc->psy_fuel_gauge);
839 ret = -ENODEV;
840 goto err_chg_stat;
841 }
842
843 if (desc->polling_interval_ms == 0 ||
844 msecs_to_jiffies(desc->polling_interval_ms) <= CM_JIFFIES_SMALL) {
845 dev_err(&pdev->dev, "polling_interval_ms is too small\n");
846 ret = -EINVAL;
847 goto err_chg_stat;
848 }
849
850 if (!desc->temperature_out_of_range) {
851 dev_err(&pdev->dev, "there is no temperature_out_of_range\n");
852 ret = -EINVAL;
853 goto err_chg_stat;
854 }
855
856 platform_set_drvdata(pdev, cm);
857
858 memcpy(&cm->charger_psy, &psy_default,
859 sizeof(psy_default));
860 if (!desc->psy_name) {
861 strncpy(cm->psy_name_buf, psy_default.name,
862 PSY_NAME_MAX);
863 } else {
864 strncpy(cm->psy_name_buf, desc->psy_name, PSY_NAME_MAX);
865 }
866 cm->charger_psy.name = cm->psy_name_buf;
867
868 /* Allocate for psy properties because they may vary */
869 cm->charger_psy.properties = kzalloc(sizeof(enum power_supply_property)
870 * (ARRAY_SIZE(default_charger_props) +
871 NUM_CHARGER_PSY_OPTIONAL),
872 GFP_KERNEL);
873 if (!cm->charger_psy.properties) {
874 dev_err(&pdev->dev, "Cannot allocate for psy properties.\n");
875 ret = -ENOMEM;
876 goto err_chg_stat;
877 }
878 memcpy(cm->charger_psy.properties, default_charger_props,
879 sizeof(enum power_supply_property) *
880 ARRAY_SIZE(default_charger_props));
881 cm->charger_psy.num_properties = psy_default.num_properties;
882
883 /* Find which optional psy-properties are available */
884 if (!cm->fuel_gauge->get_property(cm->fuel_gauge,
885 POWER_SUPPLY_PROP_CHARGE_NOW, &val)) {
886 cm->charger_psy.properties[cm->charger_psy.num_properties] =
887 POWER_SUPPLY_PROP_CHARGE_NOW;
888 cm->charger_psy.num_properties++;
889 }
890 if (!cm->fuel_gauge->get_property(cm->fuel_gauge,
891 POWER_SUPPLY_PROP_CURRENT_NOW,
892 &val)) {
893 cm->charger_psy.properties[cm->charger_psy.num_properties] =
894 POWER_SUPPLY_PROP_CURRENT_NOW;
895 cm->charger_psy.num_properties++;
896 }
897 if (!desc->measure_battery_temp) {
898 cm->charger_psy.properties[cm->charger_psy.num_properties] =
899 POWER_SUPPLY_PROP_TEMP_AMBIENT;
900 cm->charger_psy.num_properties++;
901 }
902 if (desc->measure_battery_temp) {
903 cm->charger_psy.properties[cm->charger_psy.num_properties] =
904 POWER_SUPPLY_PROP_TEMP;
905 cm->charger_psy.num_properties++;
906 }
907
908 ret = power_supply_register(NULL, &cm->charger_psy);
909 if (ret) {
910 dev_err(&pdev->dev, "Cannot register charger-manager with"
911 " name \"%s\".\n", cm->charger_psy.name);
912 goto err_register;
913 }
914
915 ret = regulator_bulk_get(&pdev->dev, desc->num_charger_regulators,
916 desc->charger_regulators);
917 if (ret) {
918 dev_err(&pdev->dev, "Cannot get charger regulators.\n");
919 goto err_bulk_get;
920 }
921
922 ret = try_charger_enable(cm, true);
923 if (ret) {
924 dev_err(&pdev->dev, "Cannot enable charger regulators\n");
925 goto err_chg_enable;
926 }
927
928 /* Add to the list */
929 mutex_lock(&cm_list_mtx);
930 list_add(&cm->entry, &cm_list);
931 mutex_unlock(&cm_list_mtx);
932
933 return 0;
934
935err_chg_enable:
936 if (desc->charger_regulators)
937 regulator_bulk_free(desc->num_charger_regulators,
938 desc->charger_regulators);
939err_bulk_get:
940 power_supply_unregister(&cm->charger_psy);
941err_register:
942 kfree(cm->charger_psy.properties);
943err_chg_stat:
944 kfree(cm->charger_stat);
945err_no_charger_stat:
946err_no_charger:
947 kfree(cm->desc);
948err_alloc_desc:
949 kfree(cm);
950err_alloc:
951 return ret;
952}
953
954static int __devexit charger_manager_remove(struct platform_device *pdev)
955{
956 struct charger_manager *cm = platform_get_drvdata(pdev);
957 struct charger_desc *desc = cm->desc;
958
959 /* Remove from the list */
960 mutex_lock(&cm_list_mtx);
961 list_del(&cm->entry);
962 mutex_unlock(&cm_list_mtx);
963
964 if (desc->charger_regulators)
965 regulator_bulk_free(desc->num_charger_regulators,
966 desc->charger_regulators);
967
968 power_supply_unregister(&cm->charger_psy);
969 kfree(cm->charger_psy.properties);
970 kfree(cm->charger_stat);
971 kfree(cm->desc);
972 kfree(cm);
973
974 return 0;
975}
976
977const struct platform_device_id charger_manager_id[] = {
978 { "charger-manager", 0 },
979 { },
980};
981
982static int cm_suspend_prepare(struct device *dev)
983{
984 struct platform_device *pdev = container_of(dev, struct platform_device,
985 dev);
986 struct charger_manager *cm = platform_get_drvdata(pdev);
987
988 if (!cm_suspended) {
989 if (rtc_dev) {
990 struct rtc_time tmp;
991 unsigned long now;
992
993 rtc_read_alarm(rtc_dev, &rtc_wkalarm_save);
994 rtc_read_time(rtc_dev, &tmp);
995
996 if (rtc_wkalarm_save.enabled) {
997 rtc_tm_to_time(&rtc_wkalarm_save.time,
998 &rtc_wkalarm_save_time);
999 rtc_tm_to_time(&tmp, &now);
1000 if (now > rtc_wkalarm_save_time)
1001 rtc_wkalarm_save_time = 0;
1002 } else {
1003 rtc_wkalarm_save_time = 0;
1004 }
1005 }
1006 cm_suspended = true;
1007 }
1008
1009 cm->status_save_ext_pwr_inserted = is_ext_pwr_online(cm);
1010 cm->status_save_batt = is_batt_present(cm);
1011
1012 if (!cm_rtc_set) {
1013 cm_suspend_duration_ms = 0;
1014 cm_rtc_set = cm_setup_timer();
1015 }
1016
1017 return 0;
1018}
1019
1020static void cm_suspend_complete(struct device *dev)
1021{
1022 struct platform_device *pdev = container_of(dev, struct platform_device,
1023 dev);
1024 struct charger_manager *cm = platform_get_drvdata(pdev);
1025
1026 if (cm_suspended) {
1027 if (rtc_dev) {
1028 struct rtc_wkalrm tmp;
1029
1030 rtc_read_alarm(rtc_dev, &tmp);
1031 rtc_wkalarm_save.pending = tmp.pending;
1032 rtc_set_alarm(rtc_dev, &rtc_wkalarm_save);
1033 }
1034 cm_suspended = false;
1035 cm_rtc_set = false;
1036 }
1037
1038 uevent_notify(cm, NULL);
1039}
1040
1041static const struct dev_pm_ops charger_manager_pm = {
1042 .prepare = cm_suspend_prepare,
1043 .complete = cm_suspend_complete,
1044};
1045
1046static struct platform_driver charger_manager_driver = {
1047 .driver = {
1048 .name = "charger-manager",
1049 .owner = THIS_MODULE,
1050 .pm = &charger_manager_pm,
1051 },
1052 .probe = charger_manager_probe,
1053 .remove = __devexit_p(charger_manager_remove),
1054 .id_table = charger_manager_id,
1055};
1056
1057static int __init charger_manager_init(void)
1058{
1059 return platform_driver_register(&charger_manager_driver);
1060}
1061late_initcall(charger_manager_init);
1062
1063static void __exit charger_manager_cleanup(void)
1064{
1065 platform_driver_unregister(&charger_manager_driver);
1066}
1067module_exit(charger_manager_cleanup);
1068
1069MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
1070MODULE_DESCRIPTION("Charger Manager");
1071MODULE_LICENSE("GPL");
1072MODULE_ALIAS("charger-manager");
diff --git a/drivers/power/collie_battery.c b/drivers/power/collie_battery.c
index 548d263b1ad..74c6b23aeab 100644
--- a/drivers/power/collie_battery.c
+++ b/drivers/power/collie_battery.c
@@ -146,7 +146,7 @@ static void collie_bat_external_power_changed(struct power_supply *psy)
146 146
147static irqreturn_t collie_bat_gpio_isr(int irq, void *data) 147static irqreturn_t collie_bat_gpio_isr(int irq, void *data)
148{ 148{
149 pr_info("collie_bat_gpio irq: %d\n", gpio_get_value(irq_to_gpio(irq))); 149 pr_info("collie_bat_gpio irq\n");
150 schedule_work(&bat_work); 150 schedule_work(&bat_work);
151 return IRQ_HANDLED; 151 return IRQ_HANDLED;
152} 152}
@@ -277,18 +277,13 @@ static struct collie_bat collie_bat_bu = {
277 .adc_temp_divider = -1, 277 .adc_temp_divider = -1,
278}; 278};
279 279
280static struct { 280static struct gpio collie_batt_gpios[] = {
281 int gpio; 281 { COLLIE_GPIO_CO, GPIOF_IN, "main battery full" },
282 char *name; 282 { COLLIE_GPIO_MAIN_BAT_LOW, GPIOF_IN, "main battery low" },
283 bool output; 283 { COLLIE_GPIO_CHARGE_ON, GPIOF_OUT_INIT_LOW, "main charge on" },
284 int value; 284 { COLLIE_GPIO_MBAT_ON, GPIOF_OUT_INIT_LOW, "main battery" },
285} gpios[] = { 285 { COLLIE_GPIO_TMP_ON, GPIOF_OUT_INIT_LOW, "main battery temp" },
286 { COLLIE_GPIO_CO, "main battery full", 0, 0 }, 286 { COLLIE_GPIO_BBAT_ON, GPIOF_OUT_INIT_LOW, "backup battery" },
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}; 287};
293 288
294#ifdef CONFIG_PM 289#ifdef CONFIG_PM
@@ -313,29 +308,16 @@ static int collie_bat_resume(struct ucb1x00_dev *dev)
313static int __devinit collie_bat_probe(struct ucb1x00_dev *dev) 308static int __devinit collie_bat_probe(struct ucb1x00_dev *dev)
314{ 309{
315 int ret; 310 int ret;
316 int i;
317 311
318 if (!machine_is_collie()) 312 if (!machine_is_collie())
319 return -ENODEV; 313 return -ENODEV;
320 314
321 ucb = dev->ucb; 315 ucb = dev->ucb;
322 316
323 for (i = 0; i < ARRAY_SIZE(gpios); i++) { 317 ret = gpio_request_array(collie_batt_gpios,
324 ret = gpio_request(gpios[i].gpio, gpios[i].name); 318 ARRAY_SIZE(collie_batt_gpios));
325 if (ret) { 319 if (ret)
326 i--; 320 return ret;
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 321
340 mutex_init(&collie_bat_main.work_lock); 322 mutex_init(&collie_bat_main.work_lock);
341 323
@@ -363,19 +345,12 @@ err_psy_reg_main:
363 345
364 /* see comment in collie_bat_remove */ 346 /* see comment in collie_bat_remove */
365 cancel_work_sync(&bat_work); 347 cancel_work_sync(&bat_work);
366 348 gpio_free_array(collie_batt_gpios, ARRAY_SIZE(collie_batt_gpios));
367 i--;
368err_gpio:
369 for (; i >= 0; i--)
370 gpio_free(gpios[i].gpio);
371
372 return ret; 349 return ret;
373} 350}
374 351
375static void __devexit collie_bat_remove(struct ucb1x00_dev *dev) 352static void __devexit collie_bat_remove(struct ucb1x00_dev *dev)
376{ 353{
377 int i;
378
379 free_irq(gpio_to_irq(COLLIE_GPIO_CO), &collie_bat_main); 354 free_irq(gpio_to_irq(COLLIE_GPIO_CO), &collie_bat_main);
380 355
381 power_supply_unregister(&collie_bat_bu.psy); 356 power_supply_unregister(&collie_bat_bu.psy);
@@ -387,9 +362,7 @@ static void __devexit collie_bat_remove(struct ucb1x00_dev *dev)
387 * unregistered now. 362 * unregistered now.
388 */ 363 */
389 cancel_work_sync(&bat_work); 364 cancel_work_sync(&bat_work);
390 365 gpio_free_array(collie_batt_gpios, ARRAY_SIZE(collie_batt_gpios));
391 for (i = ARRAY_SIZE(gpios) - 1; i >= 0; i--)
392 gpio_free(gpios[i].gpio);
393} 366}
394 367
395static struct ucb1x00_driver collie_bat_driver = { 368static struct ucb1x00_driver collie_bat_driver = {
diff --git a/drivers/power/da9030_battery.c b/drivers/power/da9030_battery.c
index d2c793cf676..3fd3e95d2b8 100644
--- a/drivers/power/da9030_battery.c
+++ b/drivers/power/da9030_battery.c
@@ -588,18 +588,7 @@ static struct platform_driver da903x_battery_driver = {
588 .remove = da9030_battery_remove, 588 .remove = da9030_battery_remove,
589}; 589};
590 590
591static int da903x_battery_init(void) 591module_platform_driver(da903x_battery_driver);
592{
593 return platform_driver_register(&da903x_battery_driver);
594}
595
596static void da903x_battery_exit(void)
597{
598 platform_driver_unregister(&da903x_battery_driver);
599}
600
601module_init(da903x_battery_init);
602module_exit(da903x_battery_exit);
603 592
604MODULE_DESCRIPTION("DA9030 battery charger driver"); 593MODULE_DESCRIPTION("DA9030 battery charger driver");
605MODULE_AUTHOR("Mike Rapoport, CompuLab"); 594MODULE_AUTHOR("Mike Rapoport, CompuLab");
diff --git a/drivers/power/da9052-battery.c b/drivers/power/da9052-battery.c
new file mode 100644
index 00000000000..e8ea47a53de
--- /dev/null
+++ b/drivers/power/da9052-battery.c
@@ -0,0 +1,664 @@
1/*
2 * Batttery Driver for Dialog DA9052 PMICs
3 *
4 * Copyright(c) 2011 Dialog Semiconductor Ltd.
5 *
6 * Author: David Dajun Chen <dchen@diasemi.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
13
14#include <linux/delay.h>
15#include <linux/freezer.h>
16#include <linux/fs.h>
17#include <linux/jiffies.h>
18#include <linux/module.h>
19#include <linux/timer.h>
20#include <linux/uaccess.h>
21#include <linux/platform_device.h>
22#include <linux/power_supply.h>
23
24#include <linux/mfd/da9052/da9052.h>
25#include <linux/mfd/da9052/pdata.h>
26#include <linux/mfd/da9052/reg.h>
27
28/* STATIC CONFIGURATION */
29#define DA9052_BAT_CUTOFF_VOLT 2800
30#define DA9052_BAT_TSH 62000
31#define DA9052_BAT_LOW_CAP 4
32#define DA9052_AVG_SZ 4
33#define DA9052_VC_TBL_SZ 68
34#define DA9052_VC_TBL_REF_SZ 3
35
36#define DA9052_ISET_USB_MASK 0x0F
37#define DA9052_CHG_USB_ILIM_MASK 0x40
38#define DA9052_CHG_LIM_COLS 16
39
40#define DA9052_MEAN(x, y) ((x + y) / 2)
41
42enum charger_type_enum {
43 DA9052_NOCHARGER = 1,
44 DA9052_CHARGER,
45};
46
47static const u16 da9052_chg_current_lim[2][DA9052_CHG_LIM_COLS] = {
48 {70, 80, 90, 100, 110, 120, 400, 450,
49 500, 550, 600, 650, 700, 900, 1100, 1300},
50 {80, 90, 100, 110, 120, 400, 450, 500,
51 550, 600, 800, 1000, 1200, 1400, 1600, 1800},
52};
53
54static const u16 vc_tbl_ref[3] = {10, 25, 40};
55/* Lookup table for voltage vs capacity */
56static u32 const vc_tbl[3][68][2] = {
57 /* For temperature 10 degree Celsius */
58 {
59 {4082, 100}, {4036, 98},
60 {4020, 96}, {4008, 95},
61 {3997, 93}, {3983, 91},
62 {3964, 90}, {3943, 88},
63 {3926, 87}, {3912, 85},
64 {3900, 84}, {3890, 82},
65 {3881, 80}, {3873, 79},
66 {3865, 77}, {3857, 76},
67 {3848, 74}, {3839, 73},
68 {3829, 71}, {3820, 70},
69 {3811, 68}, {3802, 67},
70 {3794, 65}, {3785, 64},
71 {3778, 62}, {3770, 61},
72 {3763, 59}, {3756, 58},
73 {3750, 56}, {3744, 55},
74 {3738, 53}, {3732, 52},
75 {3727, 50}, {3722, 49},
76 {3717, 47}, {3712, 46},
77 {3708, 44}, {3703, 43},
78 {3700, 41}, {3696, 40},
79 {3693, 38}, {3691, 37},
80 {3688, 35}, {3686, 34},
81 {3683, 32}, {3681, 31},
82 {3678, 29}, {3675, 28},
83 {3672, 26}, {3669, 25},
84 {3665, 23}, {3661, 22},
85 {3656, 21}, {3651, 19},
86 {3645, 18}, {3639, 16},
87 {3631, 15}, {3622, 13},
88 {3611, 12}, {3600, 10},
89 {3587, 9}, {3572, 7},
90 {3548, 6}, {3503, 5},
91 {3420, 3}, {3268, 2},
92 {2992, 1}, {2746, 0}
93 },
94 /* For temperature 25 degree Celsius */
95 {
96 {4102, 100}, {4065, 98},
97 {4048, 96}, {4034, 95},
98 {4021, 93}, {4011, 92},
99 {4001, 90}, {3986, 88},
100 {3968, 87}, {3952, 85},
101 {3938, 84}, {3926, 82},
102 {3916, 81}, {3908, 79},
103 {3900, 77}, {3892, 76},
104 {3883, 74}, {3874, 73},
105 {3864, 71}, {3855, 70},
106 {3846, 68}, {3836, 67},
107 {3827, 65}, {3819, 64},
108 {3810, 62}, {3801, 61},
109 {3793, 59}, {3786, 58},
110 {3778, 56}, {3772, 55},
111 {3765, 53}, {3759, 52},
112 {3754, 50}, {3748, 49},
113 {3743, 47}, {3738, 46},
114 {3733, 44}, {3728, 43},
115 {3724, 41}, {3720, 40},
116 {3716, 38}, {3712, 37},
117 {3709, 35}, {3706, 34},
118 {3703, 33}, {3701, 31},
119 {3698, 30}, {3696, 28},
120 {3693, 27}, {3690, 25},
121 {3687, 24}, {3683, 22},
122 {3680, 21}, {3675, 19},
123 {3671, 18}, {3666, 17},
124 {3660, 15}, {3654, 14},
125 {3647, 12}, {3639, 11},
126 {3630, 9}, {3621, 8},
127 {3613, 6}, {3606, 5},
128 {3597, 4}, {3582, 2},
129 {3546, 1}, {2747, 0}
130 },
131 /* For temperature 40 degree Celsius */
132 {
133 {4114, 100}, {4081, 98},
134 {4065, 96}, {4050, 95},
135 {4036, 93}, {4024, 92},
136 {4013, 90}, {4002, 88},
137 {3990, 87}, {3976, 85},
138 {3962, 84}, {3950, 82},
139 {3939, 81}, {3930, 79},
140 {3921, 77}, {3912, 76},
141 {3902, 74}, {3893, 73},
142 {3883, 71}, {3874, 70},
143 {3865, 68}, {3856, 67},
144 {3847, 65}, {3838, 64},
145 {3829, 62}, {3820, 61},
146 {3812, 59}, {3803, 58},
147 {3795, 56}, {3787, 55},
148 {3780, 53}, {3773, 52},
149 {3767, 50}, {3761, 49},
150 {3756, 47}, {3751, 46},
151 {3746, 44}, {3741, 43},
152 {3736, 41}, {3732, 40},
153 {3728, 38}, {3724, 37},
154 {3720, 35}, {3716, 34},
155 {3713, 33}, {3710, 31},
156 {3707, 30}, {3704, 28},
157 {3701, 27}, {3698, 25},
158 {3695, 24}, {3691, 22},
159 {3686, 21}, {3681, 19},
160 {3676, 18}, {3671, 17},
161 {3666, 15}, {3661, 14},
162 {3655, 12}, {3648, 11},
163 {3640, 9}, {3632, 8},
164 {3622, 6}, {3616, 5},
165 {3611, 4}, {3604, 2},
166 {3594, 1}, {2747, 0}
167 }
168};
169
170struct da9052_battery {
171 struct da9052 *da9052;
172 struct power_supply psy;
173 struct notifier_block nb;
174 int charger_type;
175 int status;
176 int health;
177};
178
179static inline int volt_reg_to_mV(int value)
180{
181 return ((value * 1000) / 512) + 2500;
182}
183
184static inline int ichg_reg_to_mA(int value)
185{
186 return (value * 3900) / 1000;
187}
188
189static int da9052_read_chgend_current(struct da9052_battery *bat,
190 int *current_mA)
191{
192 int ret;
193
194 if (bat->status == POWER_SUPPLY_STATUS_DISCHARGING)
195 return -EINVAL;
196
197 ret = da9052_reg_read(bat->da9052, DA9052_ICHG_END_REG);
198 if (ret < 0)
199 return ret;
200
201 *current_mA = ichg_reg_to_mA(ret & DA9052_ICHGEND_ICHGEND);
202
203 return 0;
204}
205
206static int da9052_read_chg_current(struct da9052_battery *bat, int *current_mA)
207{
208 int ret;
209
210 if (bat->status == POWER_SUPPLY_STATUS_DISCHARGING)
211 return -EINVAL;
212
213 ret = da9052_reg_read(bat->da9052, DA9052_ICHG_AV_REG);
214 if (ret < 0)
215 return ret;
216
217 *current_mA = ichg_reg_to_mA(ret & DA9052_ICHGAV_ICHGAV);
218
219 return 0;
220}
221
222static int da9052_bat_check_status(struct da9052_battery *bat, int *status)
223{
224 u8 v[2] = {0, 0};
225 u8 bat_status;
226 u8 chg_end;
227 int ret;
228 int chg_current;
229 int chg_end_current;
230 bool dcinsel;
231 bool dcindet;
232 bool vbussel;
233 bool vbusdet;
234 bool dc;
235 bool vbus;
236
237 ret = da9052_group_read(bat->da9052, DA9052_STATUS_A_REG, 2, v);
238 if (ret < 0)
239 return ret;
240
241 bat_status = v[0];
242 chg_end = v[1];
243
244 dcinsel = bat_status & DA9052_STATUSA_DCINSEL;
245 dcindet = bat_status & DA9052_STATUSA_DCINDET;
246 vbussel = bat_status & DA9052_STATUSA_VBUSSEL;
247 vbusdet = bat_status & DA9052_STATUSA_VBUSDET;
248 dc = dcinsel && dcindet;
249 vbus = vbussel && vbusdet;
250
251 /* Preference to WALL(DCIN) charger unit */
252 if (dc || vbus) {
253 bat->charger_type = DA9052_CHARGER;
254
255 /* If charging end flag is set and Charging current is greater
256 * than charging end limit then battery is charging
257 */
258 if ((chg_end & DA9052_STATUSB_CHGEND) != 0) {
259 ret = da9052_read_chg_current(bat, &chg_current);
260 if (ret < 0)
261 return ret;
262 ret = da9052_read_chgend_current(bat, &chg_end_current);
263 if (ret < 0)
264 return ret;
265
266 if (chg_current >= chg_end_current)
267 bat->status = POWER_SUPPLY_STATUS_CHARGING;
268 else
269 bat->status = POWER_SUPPLY_STATUS_NOT_CHARGING;
270 } else {
271 /* If Charging end flag is cleared then battery is
272 * charging
273 */
274 bat->status = POWER_SUPPLY_STATUS_CHARGING;
275 }
276 } else if (dcindet || vbusdet) {
277 bat->charger_type = DA9052_CHARGER;
278 bat->status = POWER_SUPPLY_STATUS_NOT_CHARGING;
279 } else {
280 bat->charger_type = DA9052_NOCHARGER;
281 bat->status = POWER_SUPPLY_STATUS_DISCHARGING;
282 }
283
284 if (status != NULL)
285 *status = bat->status;
286 return 0;
287}
288
289static int da9052_bat_read_volt(struct da9052_battery *bat, int *volt_mV)
290{
291 int volt;
292
293 volt = da9052_adc_manual_read(bat->da9052, DA9052_ADC_MAN_MUXSEL_VBAT);
294 if (volt < 0)
295 return volt;
296
297 *volt_mV = volt_reg_to_mV(volt);
298
299 return 0;
300}
301
302static int da9052_bat_check_presence(struct da9052_battery *bat, int *illegal)
303{
304 int bat_temp;
305
306 bat_temp = da9052_adc_read_temp(bat->da9052);
307 if (bat_temp < 0)
308 return bat_temp;
309
310 if (bat_temp > DA9052_BAT_TSH)
311 *illegal = 1;
312 else
313 *illegal = 0;
314
315 return 0;
316}
317
318static int da9052_bat_interpolate(int vbat_lower, int vbat_upper,
319 int level_lower, int level_upper,
320 int bat_voltage)
321{
322 int tmp;
323
324 tmp = ((level_upper - level_lower) * 1000) / (vbat_upper - vbat_lower);
325 tmp = level_lower + (((bat_voltage - vbat_lower) * tmp) / 1000);
326
327 return tmp;
328}
329
330unsigned char da9052_determine_vc_tbl_index(unsigned char adc_temp)
331{
332 int i;
333
334 if (adc_temp <= vc_tbl_ref[0])
335 return 0;
336
337 if (adc_temp > vc_tbl_ref[DA9052_VC_TBL_REF_SZ - 1])
338 return DA9052_VC_TBL_REF_SZ - 1;
339
340 for (i = 0; i < DA9052_VC_TBL_REF_SZ; i++) {
341 if ((adc_temp > vc_tbl_ref[i]) &&
342 (adc_temp <= DA9052_MEAN(vc_tbl_ref[i], vc_tbl_ref[i + 1])))
343 return i;
344 if ((adc_temp > DA9052_MEAN(vc_tbl_ref[i], vc_tbl_ref[i + 1]))
345 && (adc_temp <= vc_tbl_ref[i]))
346 return i + 1;
347 }
348}
349
350static int da9052_bat_read_capacity(struct da9052_battery *bat, int *capacity)
351{
352 int adc_temp;
353 int bat_voltage;
354 int vbat_lower;
355 int vbat_upper;
356 int level_upper;
357 int level_lower;
358 int ret;
359 int flag;
360 int i = 0;
361 int j;
362
363 ret = da9052_bat_read_volt(bat, &bat_voltage);
364 if (ret < 0)
365 return ret;
366
367 adc_temp = da9052_adc_read_temp(bat->da9052);
368 if (adc_temp < 0)
369 return adc_temp;
370
371 i = da9052_determine_vc_tbl_index(adc_temp);
372
373 if (bat_voltage >= vc_tbl[i][0][0]) {
374 *capacity = 100;
375 return 0;
376 }
377 if (bat_voltage <= vc_tbl[i][DA9052_VC_TBL_SZ - 1][0]) {
378 *capacity = 0;
379 return 0;
380 }
381 flag = 0;
382
383 for (j = 0; j < (DA9052_VC_TBL_SZ-1); j++) {
384 if ((bat_voltage <= vc_tbl[i][j][0]) &&
385 (bat_voltage >= vc_tbl[i][j + 1][0])) {
386 vbat_upper = vc_tbl[i][j][0];
387 vbat_lower = vc_tbl[i][j + 1][0];
388 level_upper = vc_tbl[i][j][1];
389 level_lower = vc_tbl[i][j + 1][1];
390 flag = 1;
391 break;
392 }
393 }
394 if (!flag)
395 return -EIO;
396
397 *capacity = da9052_bat_interpolate(vbat_lower, vbat_upper, level_lower,
398 level_upper, bat_voltage);
399
400 return 0;
401}
402
403static int da9052_bat_check_health(struct da9052_battery *bat, int *health)
404{
405 int ret;
406 int bat_illegal;
407 int capacity;
408
409 ret = da9052_bat_check_presence(bat, &bat_illegal);
410 if (ret < 0)
411 return ret;
412
413 if (bat_illegal) {
414 bat->health = POWER_SUPPLY_HEALTH_UNKNOWN;
415 return 0;
416 }
417
418 if (bat->health != POWER_SUPPLY_HEALTH_OVERHEAT) {
419 ret = da9052_bat_read_capacity(bat, &capacity);
420 if (ret < 0)
421 return ret;
422 if (capacity < DA9052_BAT_LOW_CAP)
423 bat->health = POWER_SUPPLY_HEALTH_DEAD;
424 else
425 bat->health = POWER_SUPPLY_HEALTH_GOOD;
426 }
427
428 *health = bat->health;
429
430 return 0;
431}
432
433static irqreturn_t da9052_bat_irq(int irq, void *data)
434{
435 struct da9052_battery *bat = data;
436
437 irq -= bat->da9052->irq_base;
438
439 if (irq == DA9052_IRQ_CHGEND)
440 bat->status = POWER_SUPPLY_STATUS_FULL;
441 else
442 da9052_bat_check_status(bat, NULL);
443
444 if (irq == DA9052_IRQ_CHGEND || irq == DA9052_IRQ_DCIN ||
445 irq == DA9052_IRQ_VBUS || irq == DA9052_IRQ_TBAT) {
446 power_supply_changed(&bat->psy);
447 }
448
449 return IRQ_HANDLED;
450}
451
452static int da9052_USB_current_notifier(struct notifier_block *nb,
453 unsigned long events, void *data)
454{
455 u8 row;
456 u8 col;
457 int *current_mA = data;
458 int ret;
459 struct da9052_battery *bat = container_of(nb, struct da9052_battery,
460 nb);
461
462 if (bat->status == POWER_SUPPLY_STATUS_DISCHARGING)
463 return -EPERM;
464
465 ret = da9052_reg_read(bat->da9052, DA9052_CHGBUCK_REG);
466 if (ret & DA9052_CHG_USB_ILIM_MASK)
467 return -EPERM;
468
469 if (bat->da9052->chip_id == DA9052)
470 row = 0;
471 else
472 row = 1;
473
474 if (*current_mA < da9052_chg_current_lim[row][0] ||
475 *current_mA > da9052_chg_current_lim[row][DA9052_CHG_LIM_COLS - 1])
476 return -EINVAL;
477
478 for (col = 0; col <= DA9052_CHG_LIM_COLS - 1 ; col++) {
479 if (*current_mA <= da9052_chg_current_lim[row][col])
480 break;
481 }
482
483 return da9052_reg_update(bat->da9052, DA9052_ISET_REG,
484 DA9052_ISET_USB_MASK, col);
485}
486
487static int da9052_bat_get_property(struct power_supply *psy,
488 enum power_supply_property psp,
489 union power_supply_propval *val)
490{
491 int ret;
492 int illegal;
493 struct da9052_battery *bat = container_of(psy, struct da9052_battery,
494 psy);
495
496 ret = da9052_bat_check_presence(bat, &illegal);
497 if (ret < 0)
498 return ret;
499
500 if (illegal && psp != POWER_SUPPLY_PROP_PRESENT)
501 return -ENODEV;
502
503 switch (psp) {
504 case POWER_SUPPLY_PROP_STATUS:
505 ret = da9052_bat_check_status(bat, &val->intval);
506 break;
507 case POWER_SUPPLY_PROP_ONLINE:
508 val->intval =
509 (bat->charger_type == DA9052_NOCHARGER) ? 0 : 1;
510 break;
511 case POWER_SUPPLY_PROP_PRESENT:
512 ret = da9052_bat_check_presence(bat, &val->intval);
513 break;
514 case POWER_SUPPLY_PROP_HEALTH:
515 ret = da9052_bat_check_health(bat, &val->intval);
516 break;
517 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
518 val->intval = DA9052_BAT_CUTOFF_VOLT * 1000;
519 break;
520 case POWER_SUPPLY_PROP_VOLTAGE_AVG:
521 ret = da9052_bat_read_volt(bat, &val->intval);
522 break;
523 case POWER_SUPPLY_PROP_CURRENT_AVG:
524 ret = da9052_read_chg_current(bat, &val->intval);
525 break;
526 case POWER_SUPPLY_PROP_CAPACITY:
527 ret = da9052_bat_read_capacity(bat, &val->intval);
528 break;
529 case POWER_SUPPLY_PROP_TEMP:
530 val->intval = da9052_adc_read_temp(bat->da9052);
531 ret = val->intval;
532 break;
533 case POWER_SUPPLY_PROP_TECHNOLOGY:
534 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
535 break;
536 default:
537 return -EINVAL;
538 }
539 return ret;
540}
541
542static enum power_supply_property da9052_bat_props[] = {
543 POWER_SUPPLY_PROP_STATUS,
544 POWER_SUPPLY_PROP_ONLINE,
545 POWER_SUPPLY_PROP_PRESENT,
546 POWER_SUPPLY_PROP_HEALTH,
547 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
548 POWER_SUPPLY_PROP_VOLTAGE_AVG,
549 POWER_SUPPLY_PROP_CURRENT_AVG,
550 POWER_SUPPLY_PROP_CAPACITY,
551 POWER_SUPPLY_PROP_TEMP,
552 POWER_SUPPLY_PROP_TECHNOLOGY,
553};
554
555static struct power_supply template_battery = {
556 .name = "da9052-bat",
557 .type = POWER_SUPPLY_TYPE_BATTERY,
558 .properties = da9052_bat_props,
559 .num_properties = ARRAY_SIZE(da9052_bat_props),
560 .get_property = da9052_bat_get_property,
561};
562
563static const char *const da9052_bat_irqs[] = {
564 "BATT TEMP",
565 "DCIN DET",
566 "DCIN REM",
567 "VBUS DET",
568 "VBUS REM",
569 "CHG END",
570};
571
572static s32 __devinit da9052_bat_probe(struct platform_device *pdev)
573{
574 struct da9052_pdata *pdata;
575 struct da9052_battery *bat;
576 int ret;
577 int irq;
578 int i;
579
580 bat = kzalloc(sizeof(struct da9052_battery), GFP_KERNEL);
581 if (!bat)
582 return -ENOMEM;
583
584 bat->da9052 = dev_get_drvdata(pdev->dev.parent);
585 bat->psy = template_battery;
586 bat->charger_type = DA9052_NOCHARGER;
587 bat->status = POWER_SUPPLY_STATUS_UNKNOWN;
588 bat->health = POWER_SUPPLY_HEALTH_UNKNOWN;
589 bat->nb.notifier_call = da9052_USB_current_notifier;
590
591 pdata = bat->da9052->dev->platform_data;
592 if (pdata != NULL && pdata->use_for_apm)
593 bat->psy.use_for_apm = pdata->use_for_apm;
594 else
595 bat->psy.use_for_apm = 1;
596
597 for (i = 0; i < ARRAY_SIZE(da9052_bat_irqs); i++) {
598 irq = platform_get_irq_byname(pdev, da9052_bat_irqs[i]);
599 ret = request_threaded_irq(bat->da9052->irq_base + irq,
600 NULL, da9052_bat_irq,
601 IRQF_TRIGGER_LOW | IRQF_ONESHOT,
602 da9052_bat_irqs[i], bat);
603 if (ret != 0) {
604 dev_err(bat->da9052->dev,
605 "DA9052 failed to request %s IRQ %d: %d\n",
606 da9052_bat_irqs[i], irq, ret);
607 goto err;
608 }
609 }
610
611 ret = power_supply_register(&pdev->dev, &bat->psy);
612 if (ret)
613 goto err;
614
615 return 0;
616
617err:
618 for (; i >= 0; i--) {
619 irq = platform_get_irq_byname(pdev, da9052_bat_irqs[i]);
620 free_irq(bat->da9052->irq_base + irq, bat);
621 }
622 kfree(bat);
623 return ret;
624}
625static int __devexit da9052_bat_remove(struct platform_device *pdev)
626{
627 int i;
628 int irq;
629 struct da9052_battery *bat = platform_get_drvdata(pdev);
630
631 for (i = 0; i < ARRAY_SIZE(da9052_bat_irqs); i++) {
632 irq = platform_get_irq_byname(pdev, da9052_bat_irqs[i]);
633 free_irq(bat->da9052->irq_base + irq, bat);
634 }
635 power_supply_unregister(&bat->psy);
636
637 return 0;
638}
639
640static struct platform_driver da9052_bat_driver = {
641 .probe = da9052_bat_probe,
642 .remove = __devexit_p(da9052_bat_remove),
643 .driver = {
644 .name = "da9052-bat",
645 .owner = THIS_MODULE,
646 },
647};
648
649static int __init da9052_bat_init(void)
650{
651 return platform_driver_register(&da9052_bat_driver);
652}
653module_init(da9052_bat_init);
654
655static void __exit da9052_bat_exit(void)
656{
657 platform_driver_unregister(&da9052_bat_driver);
658}
659module_exit(da9052_bat_exit);
660
661MODULE_DESCRIPTION("DA9052 BAT Device Driver");
662MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
663MODULE_LICENSE("GPL");
664MODULE_ALIAS("platform:da9052-bat");
diff --git a/drivers/power/ds2760_battery.c b/drivers/power/ds2760_battery.c
index f2c9cc33c0f..545874b1df9 100644
--- a/drivers/power/ds2760_battery.c
+++ b/drivers/power/ds2760_battery.c
@@ -95,7 +95,11 @@ static int rated_capacities[] = {
95 2880, /* Samsung */ 95 2880, /* Samsung */
96 2880, /* BYD */ 96 2880, /* BYD */
97 2880, /* Lishen */ 97 2880, /* Lishen */
98 2880 /* NEC */ 98 2880, /* NEC */
99#ifdef CONFIG_MACH_H4700
100 0,
101 3600, /* HP iPAQ hx4700 3.7V 3600mAh (359114-001) */
102#endif
99}; 103};
100 104
101/* array is level at temps 0°C, 10°C, 20°C, 30°C, 40°C 105/* array is level at temps 0°C, 10°C, 20°C, 30°C, 40°C
@@ -637,18 +641,7 @@ static struct platform_driver ds2760_battery_driver = {
637 .resume = ds2760_battery_resume, 641 .resume = ds2760_battery_resume,
638}; 642};
639 643
640static int __init ds2760_battery_init(void) 644module_platform_driver(ds2760_battery_driver);
641{
642 return platform_driver_register(&ds2760_battery_driver);
643}
644
645static void __exit ds2760_battery_exit(void)
646{
647 platform_driver_unregister(&ds2760_battery_driver);
648}
649
650module_init(ds2760_battery_init);
651module_exit(ds2760_battery_exit);
652 645
653MODULE_LICENSE("GPL"); 646MODULE_LICENSE("GPL");
654MODULE_AUTHOR("Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>, " 647MODULE_AUTHOR("Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>, "
diff --git a/drivers/power/ds2780_battery.c b/drivers/power/ds2780_battery.c
index 91a783d7236..de31cae1ba5 100644
--- a/drivers/power/ds2780_battery.c
+++ b/drivers/power/ds2780_battery.c
@@ -841,29 +841,17 @@ static int __devexit ds2780_battery_remove(struct platform_device *pdev)
841 return 0; 841 return 0;
842} 842}
843 843
844MODULE_ALIAS("platform:ds2780-battery");
845
846static struct platform_driver ds2780_battery_driver = { 844static struct platform_driver ds2780_battery_driver = {
847 .driver = { 845 .driver = {
848 .name = "ds2780-battery", 846 .name = "ds2780-battery",
849 }, 847 },
850 .probe = ds2780_battery_probe, 848 .probe = ds2780_battery_probe,
851 .remove = ds2780_battery_remove, 849 .remove = __devexit_p(ds2780_battery_remove),
852}; 850};
853 851
854static int __init ds2780_battery_init(void) 852module_platform_driver(ds2780_battery_driver);
855{
856 return platform_driver_register(&ds2780_battery_driver);
857}
858
859static void __exit ds2780_battery_exit(void)
860{
861 platform_driver_unregister(&ds2780_battery_driver);
862}
863
864module_init(ds2780_battery_init);
865module_exit(ds2780_battery_exit);
866 853
867MODULE_LICENSE("GPL"); 854MODULE_LICENSE("GPL");
868MODULE_AUTHOR("Clifton Barnes <cabarnes@indesign-llc.com>"); 855MODULE_AUTHOR("Clifton Barnes <cabarnes@indesign-llc.com>");
869MODULE_DESCRIPTION("Maxim/Dallas DS2780 Stand-Alone Fuel Gauage IC driver"); 856MODULE_DESCRIPTION("Maxim/Dallas DS2780 Stand-Alone Fuel Gauage IC driver");
857MODULE_ALIAS("platform:ds2780-battery");
diff --git a/drivers/power/gpio-charger.c b/drivers/power/gpio-charger.c
index a64b8854cfd..8672c9177dd 100644
--- a/drivers/power/gpio-charger.c
+++ b/drivers/power/gpio-charger.c
@@ -185,17 +185,7 @@ static struct platform_driver gpio_charger_driver = {
185 }, 185 },
186}; 186};
187 187
188static int __init gpio_charger_init(void) 188module_platform_driver(gpio_charger_driver);
189{
190 return platform_driver_register(&gpio_charger_driver);
191}
192module_init(gpio_charger_init);
193
194static void __exit gpio_charger_exit(void)
195{
196 platform_driver_unregister(&gpio_charger_driver);
197}
198module_exit(gpio_charger_exit);
199 189
200MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); 190MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
201MODULE_DESCRIPTION("Driver for chargers which report their online status through a GPIO"); 191MODULE_DESCRIPTION("Driver for chargers which report their online status through a GPIO");
diff --git a/drivers/power/intel_mid_battery.c b/drivers/power/intel_mid_battery.c
index 01fa671ec97..d09649706bd 100644
--- a/drivers/power/intel_mid_battery.c
+++ b/drivers/power/intel_mid_battery.c
@@ -779,18 +779,7 @@ static struct platform_driver platform_pmic_battery_driver = {
779 .remove = __devexit_p(platform_pmic_battery_remove), 779 .remove = __devexit_p(platform_pmic_battery_remove),
780}; 780};
781 781
782static int __init platform_pmic_battery_module_init(void) 782module_platform_driver(platform_pmic_battery_driver);
783{
784 return platform_driver_register(&platform_pmic_battery_driver);
785}
786
787static void __exit platform_pmic_battery_module_exit(void)
788{
789 platform_driver_unregister(&platform_pmic_battery_driver);
790}
791
792module_init(platform_pmic_battery_module_init);
793module_exit(platform_pmic_battery_module_exit);
794 783
795MODULE_AUTHOR("Nithish Mahalingam <nithish.mahalingam@intel.com>"); 784MODULE_AUTHOR("Nithish Mahalingam <nithish.mahalingam@intel.com>");
796MODULE_DESCRIPTION("Intel Moorestown PMIC Battery Driver"); 785MODULE_DESCRIPTION("Intel Moorestown PMIC Battery Driver");
diff --git a/drivers/power/isp1704_charger.c b/drivers/power/isp1704_charger.c
index f6d72b402a8..b806667b59a 100644
--- a/drivers/power/isp1704_charger.c
+++ b/drivers/power/isp1704_charger.c
@@ -79,7 +79,7 @@ static void isp1704_charger_set_power(struct isp1704_charger *isp, bool on)
79{ 79{
80 struct isp1704_charger_data *board = isp->dev->platform_data; 80 struct isp1704_charger_data *board = isp->dev->platform_data;
81 81
82 if (board->set_power) 82 if (board && board->set_power)
83 board->set_power(on); 83 board->set_power(on);
84} 84}
85 85
@@ -494,17 +494,7 @@ static struct platform_driver isp1704_charger_driver = {
494 .remove = __devexit_p(isp1704_charger_remove), 494 .remove = __devexit_p(isp1704_charger_remove),
495}; 495};
496 496
497static int __init isp1704_charger_init(void) 497module_platform_driver(isp1704_charger_driver);
498{
499 return platform_driver_register(&isp1704_charger_driver);
500}
501module_init(isp1704_charger_init);
502
503static void __exit isp1704_charger_exit(void)
504{
505 platform_driver_unregister(&isp1704_charger_driver);
506}
507module_exit(isp1704_charger_exit);
508 498
509MODULE_ALIAS("platform:isp1704_charger"); 499MODULE_ALIAS("platform:isp1704_charger");
510MODULE_AUTHOR("Nokia Corporation"); 500MODULE_AUTHOR("Nokia Corporation");
diff --git a/drivers/power/jz4740-battery.c b/drivers/power/jz4740-battery.c
index 763f894ed18..8dbc7bfaab1 100644
--- a/drivers/power/jz4740-battery.c
+++ b/drivers/power/jz4740-battery.c
@@ -67,7 +67,7 @@ static irqreturn_t jz_battery_irq_handler(int irq, void *devid)
67 67
68static long jz_battery_read_voltage(struct jz_battery *battery) 68static long jz_battery_read_voltage(struct jz_battery *battery)
69{ 69{
70 unsigned long t; 70 long t;
71 unsigned long val; 71 unsigned long val;
72 long voltage; 72 long voltage;
73 73
@@ -441,17 +441,7 @@ static struct platform_driver jz_battery_driver = {
441 }, 441 },
442}; 442};
443 443
444static int __init jz_battery_init(void) 444module_platform_driver(jz_battery_driver);
445{
446 return platform_driver_register(&jz_battery_driver);
447}
448module_init(jz_battery_init);
449
450static void __exit jz_battery_exit(void)
451{
452 platform_driver_unregister(&jz_battery_driver);
453}
454module_exit(jz_battery_exit);
455 445
456MODULE_ALIAS("platform:jz4740-battery"); 446MODULE_ALIAS("platform:jz4740-battery");
457MODULE_LICENSE("GPL"); 447MODULE_LICENSE("GPL");
diff --git a/drivers/power/lp8727_charger.c b/drivers/power/lp8727_charger.c
new file mode 100644
index 00000000000..b15b575c070
--- /dev/null
+++ b/drivers/power/lp8727_charger.c
@@ -0,0 +1,494 @@
1/*
2 * Driver for LP8727 Micro/Mini USB IC with intergrated charger
3 *
4 * Copyright (C) 2011 National Semiconductor
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
12#include <linux/module.h>
13#include <linux/slab.h>
14#include <linux/interrupt.h>
15#include <linux/i2c.h>
16#include <linux/power_supply.h>
17#include <linux/lp8727.h>
18
19#define DEBOUNCE_MSEC 270
20
21/* Registers */
22#define CTRL1 0x1
23#define CTRL2 0x2
24#define SWCTRL 0x3
25#define INT1 0x4
26#define INT2 0x5
27#define STATUS1 0x6
28#define STATUS2 0x7
29#define CHGCTRL2 0x9
30
31/* CTRL1 register */
32#define CP_EN (1 << 0)
33#define ADC_EN (1 << 1)
34#define ID200_EN (1 << 4)
35
36/* CTRL2 register */
37#define CHGDET_EN (1 << 1)
38#define INT_EN (1 << 6)
39
40/* SWCTRL register */
41#define SW_DM1_DM (0x0 << 0)
42#define SW_DM1_U1 (0x1 << 0)
43#define SW_DM1_HiZ (0x7 << 0)
44#define SW_DP2_DP (0x0 << 3)
45#define SW_DP2_U2 (0x1 << 3)
46#define SW_DP2_HiZ (0x7 << 3)
47
48/* INT1 register */
49#define IDNO (0xF << 0)
50#define VBUS (1 << 4)
51
52/* STATUS1 register */
53#define CHGSTAT (3 << 4)
54#define CHPORT (1 << 6)
55#define DCPORT (1 << 7)
56
57/* STATUS2 register */
58#define TEMP_STAT (3 << 5)
59
60enum lp8727_dev_id {
61 ID_NONE,
62 ID_TA,
63 ID_DEDICATED_CHG,
64 ID_USB_CHG,
65 ID_USB_DS,
66 ID_MAX,
67};
68
69enum lp8727_chg_stat {
70 PRECHG,
71 CC,
72 CV,
73 EOC,
74};
75
76struct lp8727_psy {
77 struct power_supply ac;
78 struct power_supply usb;
79 struct power_supply batt;
80};
81
82struct lp8727_chg {
83 struct device *dev;
84 struct i2c_client *client;
85 struct mutex xfer_lock;
86 struct delayed_work work;
87 struct workqueue_struct *irqthread;
88 struct lp8727_platform_data *pdata;
89 struct lp8727_psy *psy;
90 struct lp8727_chg_param *chg_parm;
91 enum lp8727_dev_id devid;
92};
93
94static int lp8727_i2c_read(struct lp8727_chg *pchg, u8 reg, u8 *data, u8 len)
95{
96 s32 ret;
97
98 mutex_lock(&pchg->xfer_lock);
99 ret = i2c_smbus_read_i2c_block_data(pchg->client, reg, len, data);
100 mutex_unlock(&pchg->xfer_lock);
101
102 return (ret != len) ? -EIO : 0;
103}
104
105static int lp8727_i2c_write(struct lp8727_chg *pchg, u8 reg, u8 *data, u8 len)
106{
107 s32 ret;
108
109 mutex_lock(&pchg->xfer_lock);
110 ret = i2c_smbus_write_i2c_block_data(pchg->client, reg, len, data);
111 mutex_unlock(&pchg->xfer_lock);
112
113 return ret;
114}
115
116static inline int lp8727_i2c_read_byte(struct lp8727_chg *pchg, u8 reg,
117 u8 *data)
118{
119 return lp8727_i2c_read(pchg, reg, data, 1);
120}
121
122static inline int lp8727_i2c_write_byte(struct lp8727_chg *pchg, u8 reg,
123 u8 *data)
124{
125 return lp8727_i2c_write(pchg, reg, data, 1);
126}
127
128static int lp8727_is_charger_attached(const char *name, int id)
129{
130 if (name) {
131 if (!strcmp(name, "ac"))
132 return (id == ID_TA || id == ID_DEDICATED_CHG) ? 1 : 0;
133 else if (!strcmp(name, "usb"))
134 return (id == ID_USB_CHG) ? 1 : 0;
135 }
136
137 return (id >= ID_TA && id <= ID_USB_CHG) ? 1 : 0;
138}
139
140static void lp8727_init_device(struct lp8727_chg *pchg)
141{
142 u8 val;
143
144 val = ID200_EN | ADC_EN | CP_EN;
145 if (lp8727_i2c_write_byte(pchg, CTRL1, &val))
146 dev_err(pchg->dev, "i2c write err : addr=0x%.2x\n", CTRL1);
147
148 val = INT_EN | CHGDET_EN;
149 if (lp8727_i2c_write_byte(pchg, CTRL2, &val))
150 dev_err(pchg->dev, "i2c write err : addr=0x%.2x\n", CTRL2);
151}
152
153static int lp8727_is_dedicated_charger(struct lp8727_chg *pchg)
154{
155 u8 val;
156 lp8727_i2c_read_byte(pchg, STATUS1, &val);
157 return (val & DCPORT);
158}
159
160static int lp8727_is_usb_charger(struct lp8727_chg *pchg)
161{
162 u8 val;
163 lp8727_i2c_read_byte(pchg, STATUS1, &val);
164 return (val & CHPORT);
165}
166
167static void lp8727_ctrl_switch(struct lp8727_chg *pchg, u8 sw)
168{
169 u8 val = sw;
170 lp8727_i2c_write_byte(pchg, SWCTRL, &val);
171}
172
173static void lp8727_id_detection(struct lp8727_chg *pchg, u8 id, int vbusin)
174{
175 u8 devid = ID_NONE;
176 u8 swctrl = SW_DM1_HiZ | SW_DP2_HiZ;
177
178 switch (id) {
179 case 0x5:
180 devid = ID_TA;
181 pchg->chg_parm = &pchg->pdata->ac;
182 break;
183 case 0xB:
184 if (lp8727_is_dedicated_charger(pchg)) {
185 pchg->chg_parm = &pchg->pdata->ac;
186 devid = ID_DEDICATED_CHG;
187 } else if (lp8727_is_usb_charger(pchg)) {
188 pchg->chg_parm = &pchg->pdata->usb;
189 devid = ID_USB_CHG;
190 swctrl = SW_DM1_DM | SW_DP2_DP;
191 } else if (vbusin) {
192 devid = ID_USB_DS;
193 swctrl = SW_DM1_DM | SW_DP2_DP;
194 }
195 break;
196 default:
197 devid = ID_NONE;
198 pchg->chg_parm = NULL;
199 break;
200 }
201
202 pchg->devid = devid;
203 lp8727_ctrl_switch(pchg, swctrl);
204}
205
206static void lp8727_enable_chgdet(struct lp8727_chg *pchg)
207{
208 u8 val;
209
210 lp8727_i2c_read_byte(pchg, CTRL2, &val);
211 val |= CHGDET_EN;
212 lp8727_i2c_write_byte(pchg, CTRL2, &val);
213}
214
215static void lp8727_delayed_func(struct work_struct *_work)
216{
217 u8 intstat[2], idno, vbus;
218 struct lp8727_chg *pchg =
219 container_of(_work, struct lp8727_chg, work.work);
220
221 if (lp8727_i2c_read(pchg, INT1, intstat, 2)) {
222 dev_err(pchg->dev, "can not read INT registers\n");
223 return;
224 }
225
226 idno = intstat[0] & IDNO;
227 vbus = intstat[0] & VBUS;
228
229 lp8727_id_detection(pchg, idno, vbus);
230 lp8727_enable_chgdet(pchg);
231
232 power_supply_changed(&pchg->psy->ac);
233 power_supply_changed(&pchg->psy->usb);
234 power_supply_changed(&pchg->psy->batt);
235}
236
237static irqreturn_t lp8727_isr_func(int irq, void *ptr)
238{
239 struct lp8727_chg *pchg = ptr;
240 unsigned long delay = msecs_to_jiffies(DEBOUNCE_MSEC);
241
242 queue_delayed_work(pchg->irqthread, &pchg->work, delay);
243
244 return IRQ_HANDLED;
245}
246
247static void lp8727_intr_config(struct lp8727_chg *pchg)
248{
249 INIT_DELAYED_WORK(&pchg->work, lp8727_delayed_func);
250
251 pchg->irqthread = create_singlethread_workqueue("lp8727-irqthd");
252 if (!pchg->irqthread)
253 dev_err(pchg->dev, "can not create thread for lp8727\n");
254
255 if (request_threaded_irq(pchg->client->irq,
256 NULL,
257 lp8727_isr_func,
258 IRQF_TRIGGER_FALLING, "lp8727_irq", pchg)) {
259 dev_err(pchg->dev, "lp8727 irq can not be registered\n");
260 }
261}
262
263static enum power_supply_property lp8727_charger_prop[] = {
264 POWER_SUPPLY_PROP_ONLINE,
265};
266
267static enum power_supply_property lp8727_battery_prop[] = {
268 POWER_SUPPLY_PROP_STATUS,
269 POWER_SUPPLY_PROP_HEALTH,
270 POWER_SUPPLY_PROP_PRESENT,
271 POWER_SUPPLY_PROP_VOLTAGE_NOW,
272 POWER_SUPPLY_PROP_CAPACITY,
273 POWER_SUPPLY_PROP_TEMP,
274};
275
276static char *battery_supplied_to[] = {
277 "main_batt",
278};
279
280static int lp8727_charger_get_property(struct power_supply *psy,
281 enum power_supply_property psp,
282 union power_supply_propval *val)
283{
284 struct lp8727_chg *pchg = dev_get_drvdata(psy->dev->parent);
285
286 if (psp == POWER_SUPPLY_PROP_ONLINE)
287 val->intval = lp8727_is_charger_attached(psy->name,
288 pchg->devid);
289
290 return 0;
291}
292
293static int lp8727_battery_get_property(struct power_supply *psy,
294 enum power_supply_property psp,
295 union power_supply_propval *val)
296{
297 struct lp8727_chg *pchg = dev_get_drvdata(psy->dev->parent);
298 u8 read;
299
300 switch (psp) {
301 case POWER_SUPPLY_PROP_STATUS:
302 if (lp8727_is_charger_attached(psy->name, pchg->devid)) {
303 lp8727_i2c_read_byte(pchg, STATUS1, &read);
304 if (((read & CHGSTAT) >> 4) == EOC)
305 val->intval = POWER_SUPPLY_STATUS_FULL;
306 else
307 val->intval = POWER_SUPPLY_STATUS_CHARGING;
308 } else {
309 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
310 }
311 break;
312 case POWER_SUPPLY_PROP_HEALTH:
313 lp8727_i2c_read_byte(pchg, STATUS2, &read);
314 read = (read & TEMP_STAT) >> 5;
315 if (read >= 0x1 && read <= 0x3)
316 val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
317 else
318 val->intval = POWER_SUPPLY_HEALTH_GOOD;
319 break;
320 case POWER_SUPPLY_PROP_PRESENT:
321 if (pchg->pdata->get_batt_present)
322 val->intval = pchg->pdata->get_batt_present();
323 break;
324 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
325 if (pchg->pdata->get_batt_level)
326 val->intval = pchg->pdata->get_batt_level();
327 break;
328 case POWER_SUPPLY_PROP_CAPACITY:
329 if (pchg->pdata->get_batt_capacity)
330 val->intval = pchg->pdata->get_batt_capacity();
331 break;
332 case POWER_SUPPLY_PROP_TEMP:
333 if (pchg->pdata->get_batt_temp)
334 val->intval = pchg->pdata->get_batt_temp();
335 break;
336 default:
337 break;
338 }
339
340 return 0;
341}
342
343static void lp8727_charger_changed(struct power_supply *psy)
344{
345 struct lp8727_chg *pchg = dev_get_drvdata(psy->dev->parent);
346 u8 val;
347 u8 eoc_level, ichg;
348
349 if (lp8727_is_charger_attached(psy->name, pchg->devid)) {
350 if (pchg->chg_parm) {
351 eoc_level = pchg->chg_parm->eoc_level;
352 ichg = pchg->chg_parm->ichg;
353 val = (ichg << 4) | eoc_level;
354 lp8727_i2c_write_byte(pchg, CHGCTRL2, &val);
355 }
356 }
357}
358
359static int lp8727_register_psy(struct lp8727_chg *pchg)
360{
361 struct lp8727_psy *psy;
362
363 psy = kzalloc(sizeof(*psy), GFP_KERNEL);
364 if (!psy)
365 goto err_mem;
366
367 pchg->psy = psy;
368
369 psy->ac.name = "ac";
370 psy->ac.type = POWER_SUPPLY_TYPE_MAINS;
371 psy->ac.properties = lp8727_charger_prop;
372 psy->ac.num_properties = ARRAY_SIZE(lp8727_charger_prop);
373 psy->ac.get_property = lp8727_charger_get_property;
374 psy->ac.supplied_to = battery_supplied_to;
375 psy->ac.num_supplicants = ARRAY_SIZE(battery_supplied_to);
376
377 if (power_supply_register(pchg->dev, &psy->ac))
378 goto err_psy;
379
380 psy->usb.name = "usb";
381 psy->usb.type = POWER_SUPPLY_TYPE_USB;
382 psy->usb.properties = lp8727_charger_prop;
383 psy->usb.num_properties = ARRAY_SIZE(lp8727_charger_prop);
384 psy->usb.get_property = lp8727_charger_get_property;
385 psy->usb.supplied_to = battery_supplied_to;
386 psy->usb.num_supplicants = ARRAY_SIZE(battery_supplied_to);
387
388 if (power_supply_register(pchg->dev, &psy->usb))
389 goto err_psy;
390
391 psy->batt.name = "main_batt";
392 psy->batt.type = POWER_SUPPLY_TYPE_BATTERY;
393 psy->batt.properties = lp8727_battery_prop;
394 psy->batt.num_properties = ARRAY_SIZE(lp8727_battery_prop);
395 psy->batt.get_property = lp8727_battery_get_property;
396 psy->batt.external_power_changed = lp8727_charger_changed;
397
398 if (power_supply_register(pchg->dev, &psy->batt))
399 goto err_psy;
400
401 return 0;
402
403err_mem:
404 return -ENOMEM;
405err_psy:
406 kfree(psy);
407 return -EPERM;
408}
409
410static void lp8727_unregister_psy(struct lp8727_chg *pchg)
411{
412 struct lp8727_psy *psy = pchg->psy;
413
414 if (!psy)
415 return;
416
417 power_supply_unregister(&psy->ac);
418 power_supply_unregister(&psy->usb);
419 power_supply_unregister(&psy->batt);
420 kfree(psy);
421}
422
423static int lp8727_probe(struct i2c_client *cl, const struct i2c_device_id *id)
424{
425 struct lp8727_chg *pchg;
426 int ret;
427
428 if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
429 return -EIO;
430
431 pchg = kzalloc(sizeof(*pchg), GFP_KERNEL);
432 if (!pchg)
433 return -ENOMEM;
434
435 pchg->client = cl;
436 pchg->dev = &cl->dev;
437 pchg->pdata = cl->dev.platform_data;
438 i2c_set_clientdata(cl, pchg);
439
440 mutex_init(&pchg->xfer_lock);
441
442 lp8727_init_device(pchg);
443 lp8727_intr_config(pchg);
444
445 ret = lp8727_register_psy(pchg);
446 if (ret)
447 dev_err(pchg->dev,
448 "can not register power supplies. err=%d", ret);
449
450 return 0;
451}
452
453static int __devexit lp8727_remove(struct i2c_client *cl)
454{
455 struct lp8727_chg *pchg = i2c_get_clientdata(cl);
456
457 lp8727_unregister_psy(pchg);
458 free_irq(pchg->client->irq, pchg);
459 flush_workqueue(pchg->irqthread);
460 destroy_workqueue(pchg->irqthread);
461 kfree(pchg);
462 return 0;
463}
464
465static const struct i2c_device_id lp8727_ids[] = {
466 {"lp8727", 0},
467};
468
469static struct i2c_driver lp8727_driver = {
470 .driver = {
471 .name = "lp8727",
472 },
473 .probe = lp8727_probe,
474 .remove = __devexit_p(lp8727_remove),
475 .id_table = lp8727_ids,
476};
477
478static int __init lp8727_init(void)
479{
480 return i2c_add_driver(&lp8727_driver);
481}
482
483static void __exit lp8727_exit(void)
484{
485 i2c_del_driver(&lp8727_driver);
486}
487
488module_init(lp8727_init);
489module_exit(lp8727_exit);
490
491MODULE_DESCRIPTION("National Semiconductor LP8727 charger driver");
492MODULE_AUTHOR
493 ("Woogyom Kim <milo.kim@ti.com>, Daniel Jeong <daniel.jeong@ti.com>");
494MODULE_LICENSE("GPL");
diff --git a/drivers/power/max17042_battery.c b/drivers/power/max17042_battery.c
index 9f0183c7307..86acee2f988 100644
--- a/drivers/power/max17042_battery.c
+++ b/drivers/power/max17042_battery.c
@@ -85,55 +85,79 @@ static int max17042_get_property(struct power_supply *psy,
85{ 85{
86 struct max17042_chip *chip = container_of(psy, 86 struct max17042_chip *chip = container_of(psy,
87 struct max17042_chip, battery); 87 struct max17042_chip, battery);
88 int ret;
88 89
89 switch (psp) { 90 switch (psp) {
90 case POWER_SUPPLY_PROP_PRESENT: 91 case POWER_SUPPLY_PROP_PRESENT:
91 val->intval = max17042_read_reg(chip->client, 92 ret = max17042_read_reg(chip->client, MAX17042_STATUS);
92 MAX17042_STATUS); 93 if (ret < 0)
93 if (val->intval & MAX17042_STATUS_BattAbsent) 94 return ret;
95
96 if (ret & MAX17042_STATUS_BattAbsent)
94 val->intval = 0; 97 val->intval = 0;
95 else 98 else
96 val->intval = 1; 99 val->intval = 1;
97 break; 100 break;
98 case POWER_SUPPLY_PROP_CYCLE_COUNT: 101 case POWER_SUPPLY_PROP_CYCLE_COUNT:
99 val->intval = max17042_read_reg(chip->client, 102 ret = max17042_read_reg(chip->client, MAX17042_Cycles);
100 MAX17042_Cycles); 103 if (ret < 0)
104 return ret;
105
106 val->intval = ret;
101 break; 107 break;
102 case POWER_SUPPLY_PROP_VOLTAGE_MAX: 108 case POWER_SUPPLY_PROP_VOLTAGE_MAX:
103 val->intval = max17042_read_reg(chip->client, 109 ret = max17042_read_reg(chip->client, MAX17042_MinMaxVolt);
104 MAX17042_MinMaxVolt); 110 if (ret < 0)
105 val->intval >>= 8; 111 return ret;
112
113 val->intval = ret >> 8;
106 val->intval *= 20000; /* Units of LSB = 20mV */ 114 val->intval *= 20000; /* Units of LSB = 20mV */
107 break; 115 break;
108 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: 116 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
109 val->intval = max17042_read_reg(chip->client, 117 ret = max17042_read_reg(chip->client, MAX17042_V_empty);
110 MAX17042_V_empty); 118 if (ret < 0)
111 val->intval >>= 7; 119 return ret;
120
121 val->intval = ret >> 7;
112 val->intval *= 10000; /* Units of LSB = 10mV */ 122 val->intval *= 10000; /* Units of LSB = 10mV */
113 break; 123 break;
114 case POWER_SUPPLY_PROP_VOLTAGE_NOW: 124 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
115 val->intval = max17042_read_reg(chip->client, 125 ret = max17042_read_reg(chip->client, MAX17042_VCELL);
116 MAX17042_VCELL) * 83; /* 1000 / 12 = 83 */ 126 if (ret < 0)
127 return ret;
128
129 val->intval = ret * 625 / 8;
117 break; 130 break;
118 case POWER_SUPPLY_PROP_VOLTAGE_AVG: 131 case POWER_SUPPLY_PROP_VOLTAGE_AVG:
119 val->intval = max17042_read_reg(chip->client, 132 ret = max17042_read_reg(chip->client, MAX17042_AvgVCELL);
120 MAX17042_AvgVCELL) * 83; 133 if (ret < 0)
134 return ret;
135
136 val->intval = ret * 625 / 8;
121 break; 137 break;
122 case POWER_SUPPLY_PROP_CAPACITY: 138 case POWER_SUPPLY_PROP_CAPACITY:
123 val->intval = max17042_read_reg(chip->client, 139 ret = max17042_read_reg(chip->client, MAX17042_SOC);
124 MAX17042_SOC) / 256; 140 if (ret < 0)
141 return ret;
142
143 val->intval = ret >> 8;
125 break; 144 break;
126 case POWER_SUPPLY_PROP_CHARGE_FULL: 145 case POWER_SUPPLY_PROP_CHARGE_FULL:
127 val->intval = max17042_read_reg(chip->client, 146 ret = max17042_read_reg(chip->client, MAX17042_RepSOC);
128 MAX17042_RepSOC); 147 if (ret < 0)
129 if ((val->intval / 256) >= MAX17042_BATTERY_FULL) 148 return ret;
149
150 if ((ret >> 8) >= MAX17042_BATTERY_FULL)
130 val->intval = 1; 151 val->intval = 1;
131 else if (val->intval >= 0) 152 else if (ret >= 0)
132 val->intval = 0; 153 val->intval = 0;
133 break; 154 break;
134 case POWER_SUPPLY_PROP_TEMP: 155 case POWER_SUPPLY_PROP_TEMP:
135 val->intval = max17042_read_reg(chip->client, 156 ret = max17042_read_reg(chip->client, MAX17042_TEMP);
136 MAX17042_TEMP); 157 if (ret < 0)
158 return ret;
159
160 val->intval = ret;
137 /* The value is signed. */ 161 /* The value is signed. */
138 if (val->intval & 0x8000) { 162 if (val->intval & 0x8000) {
139 val->intval = (0x7fff & ~val->intval) + 1; 163 val->intval = (0x7fff & ~val->intval) + 1;
@@ -145,24 +169,30 @@ static int max17042_get_property(struct power_supply *psy,
145 break; 169 break;
146 case POWER_SUPPLY_PROP_CURRENT_NOW: 170 case POWER_SUPPLY_PROP_CURRENT_NOW:
147 if (chip->pdata->enable_current_sense) { 171 if (chip->pdata->enable_current_sense) {
148 val->intval = max17042_read_reg(chip->client, 172 ret = max17042_read_reg(chip->client, MAX17042_Current);
149 MAX17042_Current); 173 if (ret < 0)
174 return ret;
175
176 val->intval = ret;
150 if (val->intval & 0x8000) { 177 if (val->intval & 0x8000) {
151 /* Negative */ 178 /* Negative */
152 val->intval = ~val->intval & 0x7fff; 179 val->intval = ~val->intval & 0x7fff;
153 val->intval++; 180 val->intval++;
154 val->intval *= -1; 181 val->intval *= -1;
155 } 182 }
156 val->intval >>= 4; 183 val->intval *= 1562500 / chip->pdata->r_sns;
157 val->intval *= 1000000 * 25 / chip->pdata->r_sns;
158 } else { 184 } else {
159 return -EINVAL; 185 return -EINVAL;
160 } 186 }
161 break; 187 break;
162 case POWER_SUPPLY_PROP_CURRENT_AVG: 188 case POWER_SUPPLY_PROP_CURRENT_AVG:
163 if (chip->pdata->enable_current_sense) { 189 if (chip->pdata->enable_current_sense) {
164 val->intval = max17042_read_reg(chip->client, 190 ret = max17042_read_reg(chip->client,
165 MAX17042_AvgCurrent); 191 MAX17042_AvgCurrent);
192 if (ret < 0)
193 return ret;
194
195 val->intval = ret;
166 if (val->intval & 0x8000) { 196 if (val->intval & 0x8000) {
167 /* Negative */ 197 /* Negative */
168 val->intval = ~val->intval & 0x7fff; 198 val->intval = ~val->intval & 0x7fff;
@@ -210,6 +240,9 @@ static int __devinit max17042_probe(struct i2c_client *client,
210 if (!chip->pdata->enable_current_sense) 240 if (!chip->pdata->enable_current_sense)
211 chip->battery.num_properties -= 2; 241 chip->battery.num_properties -= 2;
212 242
243 if (chip->pdata->r_sns == 0)
244 chip->pdata->r_sns = MAX17042_DEFAULT_SNS_RESISTOR;
245
213 ret = power_supply_register(&client->dev, &chip->battery); 246 ret = power_supply_register(&client->dev, &chip->battery);
214 if (ret) { 247 if (ret) {
215 dev_err(&client->dev, "failed: power supply register\n"); 248 dev_err(&client->dev, "failed: power supply register\n");
@@ -226,9 +259,6 @@ static int __devinit max17042_probe(struct i2c_client *client,
226 max17042_write_reg(client, MAX17042_CGAIN, 0x0000); 259 max17042_write_reg(client, MAX17042_CGAIN, 0x0000);
227 max17042_write_reg(client, MAX17042_MiscCFG, 0x0003); 260 max17042_write_reg(client, MAX17042_MiscCFG, 0x0003);
228 max17042_write_reg(client, MAX17042_LearnCFG, 0x0007); 261 max17042_write_reg(client, MAX17042_LearnCFG, 0x0007);
229 } else {
230 if (chip->pdata->r_sns == 0)
231 chip->pdata->r_sns = MAX17042_DEFAULT_SNS_RESISTOR;
232 } 262 }
233 263
234 return 0; 264 return 0;
diff --git a/drivers/power/max8903_charger.c b/drivers/power/max8903_charger.c
index 2595145f3bf..3e23f43e98a 100644
--- a/drivers/power/max8903_charger.c
+++ b/drivers/power/max8903_charger.c
@@ -374,19 +374,9 @@ static struct platform_driver max8903_driver = {
374 }, 374 },
375}; 375};
376 376
377static int __init max8903_init(void) 377module_platform_driver(max8903_driver);
378{
379 return platform_driver_register(&max8903_driver);
380}
381module_init(max8903_init);
382
383static void __exit max8903_exit(void)
384{
385 platform_driver_unregister(&max8903_driver);
386}
387module_exit(max8903_exit);
388 378
389MODULE_LICENSE("GPL"); 379MODULE_LICENSE("GPL");
390MODULE_DESCRIPTION("MAX8903 Charger Driver"); 380MODULE_DESCRIPTION("MAX8903 Charger Driver");
391MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>"); 381MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
392MODULE_ALIAS("max8903-charger"); 382MODULE_ALIAS("platform:max8903-charger");
diff --git a/drivers/power/max8925_power.c b/drivers/power/max8925_power.c
index a70e16d3a3d..daa333bd7eb 100644
--- a/drivers/power/max8925_power.c
+++ b/drivers/power/max8925_power.c
@@ -78,6 +78,8 @@ struct max8925_power_info {
78 unsigned batt_detect:1; /* detecing MB by ID pin */ 78 unsigned batt_detect:1; /* detecing MB by ID pin */
79 unsigned topoff_threshold:2; 79 unsigned topoff_threshold:2;
80 unsigned fast_charge:3; 80 unsigned fast_charge:3;
81 unsigned no_temp_support:1;
82 unsigned no_insert_detect:1;
81 83
82 int (*set_charger) (int); 84 int (*set_charger) (int);
83}; 85};
@@ -116,17 +118,7 @@ static irqreturn_t max8925_charger_handler(int irq, void *data)
116 case MAX8925_IRQ_VCHG_DC_F: 118 case MAX8925_IRQ_VCHG_DC_F:
117 info->ac_online = 0; 119 info->ac_online = 0;
118 __set_charger(info, 0); 120 __set_charger(info, 0);
119 dev_dbg(chip->dev, "Adapter is removal\n"); 121 dev_dbg(chip->dev, "Adapter removed\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; 122 break;
131 case MAX8925_IRQ_VCHG_THM_OK_F: 123 case MAX8925_IRQ_VCHG_THM_OK_F:
132 /* Battery is not ready yet */ 124 /* Battery is not ready yet */
@@ -168,27 +160,33 @@ static irqreturn_t max8925_charger_handler(int irq, void *data)
168static int start_measure(struct max8925_power_info *info, int type) 160static int start_measure(struct max8925_power_info *info, int type)
169{ 161{
170 unsigned char buf[2] = {0, 0}; 162 unsigned char buf[2] = {0, 0};
163 int meas_cmd;
171 int meas_reg = 0, ret; 164 int meas_reg = 0, ret;
172 165
173 switch (type) { 166 switch (type) {
174 case MEASURE_VCHG: 167 case MEASURE_VCHG:
168 meas_cmd = MAX8925_CMD_VCHG;
175 meas_reg = MAX8925_ADC_VCHG; 169 meas_reg = MAX8925_ADC_VCHG;
176 break; 170 break;
177 case MEASURE_VBBATT: 171 case MEASURE_VBBATT:
172 meas_cmd = MAX8925_CMD_VBBATT;
178 meas_reg = MAX8925_ADC_VBBATT; 173 meas_reg = MAX8925_ADC_VBBATT;
179 break; 174 break;
180 case MEASURE_VMBATT: 175 case MEASURE_VMBATT:
176 meas_cmd = MAX8925_CMD_VMBATT;
181 meas_reg = MAX8925_ADC_VMBATT; 177 meas_reg = MAX8925_ADC_VMBATT;
182 break; 178 break;
183 case MEASURE_ISNS: 179 case MEASURE_ISNS:
180 meas_cmd = MAX8925_CMD_ISNS;
184 meas_reg = MAX8925_ADC_ISNS; 181 meas_reg = MAX8925_ADC_ISNS;
185 break; 182 break;
186 default: 183 default:
187 return -EINVAL; 184 return -EINVAL;
188 } 185 }
189 186
187 max8925_reg_write(info->adc, meas_cmd, 0);
190 max8925_bulk_read(info->adc, meas_reg, 2, buf); 188 max8925_bulk_read(info->adc, meas_reg, 2, buf);
191 ret = (buf[0] << 4) | (buf[1] >> 4); 189 ret = ((buf[0]<<8) | buf[1]) >> 4;
192 190
193 return ret; 191 return ret;
194} 192}
@@ -208,7 +206,7 @@ static int max8925_ac_get_prop(struct power_supply *psy,
208 if (info->ac_online) { 206 if (info->ac_online) {
209 ret = start_measure(info, MEASURE_VCHG); 207 ret = start_measure(info, MEASURE_VCHG);
210 if (ret >= 0) { 208 if (ret >= 0) {
211 val->intval = ret << 1; /* unit is mV */ 209 val->intval = ret * 2000; /* unit is uV */
212 goto out; 210 goto out;
213 } 211 }
214 } 212 }
@@ -242,7 +240,7 @@ static int max8925_usb_get_prop(struct power_supply *psy,
242 if (info->usb_online) { 240 if (info->usb_online) {
243 ret = start_measure(info, MEASURE_VCHG); 241 ret = start_measure(info, MEASURE_VCHG);
244 if (ret >= 0) { 242 if (ret >= 0) {
245 val->intval = ret << 1; /* unit is mV */ 243 val->intval = ret * 2000; /* unit is uV */
246 goto out; 244 goto out;
247 } 245 }
248 } 246 }
@@ -266,7 +264,6 @@ static int max8925_bat_get_prop(struct power_supply *psy,
266 union power_supply_propval *val) 264 union power_supply_propval *val)
267{ 265{
268 struct max8925_power_info *info = dev_get_drvdata(psy->dev->parent); 266 struct max8925_power_info *info = dev_get_drvdata(psy->dev->parent);
269 long long int tmp = 0;
270 int ret = 0; 267 int ret = 0;
271 268
272 switch (psp) { 269 switch (psp) {
@@ -277,7 +274,7 @@ static int max8925_bat_get_prop(struct power_supply *psy,
277 if (info->bat_online) { 274 if (info->bat_online) {
278 ret = start_measure(info, MEASURE_VMBATT); 275 ret = start_measure(info, MEASURE_VMBATT);
279 if (ret >= 0) { 276 if (ret >= 0) {
280 val->intval = ret << 1; /* unit is mV */ 277 val->intval = ret * 2000; /* unit is uV */
281 ret = 0; 278 ret = 0;
282 break; 279 break;
283 } 280 }
@@ -288,8 +285,8 @@ static int max8925_bat_get_prop(struct power_supply *psy,
288 if (info->bat_online) { 285 if (info->bat_online) {
289 ret = start_measure(info, MEASURE_ISNS); 286 ret = start_measure(info, MEASURE_ISNS);
290 if (ret >= 0) { 287 if (ret >= 0) {
291 tmp = (long long int)ret * 6250 / 4096 - 3125; 288 /* assume r_sns is 0.02 */
292 ret = (int)tmp; 289 ret = ((ret * 6250) - 3125) /* uA */;
293 val->intval = 0; 290 val->intval = 0;
294 if (ret > 0) 291 if (ret > 0)
295 val->intval = ret; /* unit is mA */ 292 val->intval = ret; /* unit is mA */
@@ -365,13 +362,14 @@ static __devinit int max8925_init_charger(struct max8925_chip *chip,
365 int ret; 362 int ret;
366 363
367 REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_OVP, "ac-ovp"); 364 REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_OVP, "ac-ovp");
368 REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_F, "ac-remove"); 365 if (!info->no_insert_detect) {
369 REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_R, "ac-insert"); 366 REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_F, "ac-remove");
370 REQUEST_IRQ(MAX8925_IRQ_VCHG_USB_OVP, "usb-ovp"); 367 REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_R, "ac-insert");
371 REQUEST_IRQ(MAX8925_IRQ_VCHG_USB_F, "usb-remove"); 368 }
372 REQUEST_IRQ(MAX8925_IRQ_VCHG_USB_R, "usb-insert"); 369 if (!info->no_temp_support) {
373 REQUEST_IRQ(MAX8925_IRQ_VCHG_THM_OK_R, "batt-temp-in-range"); 370 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"); 371 REQUEST_IRQ(MAX8925_IRQ_VCHG_THM_OK_F, "batt-temp-out-range");
372 }
375 REQUEST_IRQ(MAX8925_IRQ_VCHG_SYSLOW_F, "vsys-high"); 373 REQUEST_IRQ(MAX8925_IRQ_VCHG_SYSLOW_F, "vsys-high");
376 REQUEST_IRQ(MAX8925_IRQ_VCHG_SYSLOW_R, "vsys-low"); 374 REQUEST_IRQ(MAX8925_IRQ_VCHG_SYSLOW_R, "vsys-low");
377 REQUEST_IRQ(MAX8925_IRQ_VCHG_RST, "charger-reset"); 375 REQUEST_IRQ(MAX8925_IRQ_VCHG_RST, "charger-reset");
@@ -379,9 +377,15 @@ static __devinit int max8925_init_charger(struct max8925_chip *chip,
379 REQUEST_IRQ(MAX8925_IRQ_VCHG_TOPOFF, "charger-topoff"); 377 REQUEST_IRQ(MAX8925_IRQ_VCHG_TOPOFF, "charger-topoff");
380 REQUEST_IRQ(MAX8925_IRQ_VCHG_TMR_FAULT, "charger-timer-expire"); 378 REQUEST_IRQ(MAX8925_IRQ_VCHG_TMR_FAULT, "charger-timer-expire");
381 379
382 info->ac_online = 0;
383 info->usb_online = 0; 380 info->usb_online = 0;
384 info->bat_online = 0; 381 info->bat_online = 0;
382
383 /* check for power - can miss interrupt at boot time */
384 if (start_measure(info, MEASURE_VCHG) * 2000 > 500000)
385 info->ac_online = 1;
386 else
387 info->ac_online = 0;
388
385 ret = max8925_reg_read(info->gpm, MAX8925_CHG_STATUS); 389 ret = max8925_reg_read(info->gpm, MAX8925_CHG_STATUS);
386 if (ret >= 0) { 390 if (ret >= 0) {
387 /* 391 /*
@@ -449,6 +453,8 @@ static __devinit int max8925_power_probe(struct platform_device *pdev)
449 info->ac.properties = max8925_ac_props; 453 info->ac.properties = max8925_ac_props;
450 info->ac.num_properties = ARRAY_SIZE(max8925_ac_props); 454 info->ac.num_properties = ARRAY_SIZE(max8925_ac_props);
451 info->ac.get_property = max8925_ac_get_prop; 455 info->ac.get_property = max8925_ac_get_prop;
456 info->ac.supplied_to = pdata->supplied_to;
457 info->ac.num_supplicants = pdata->num_supplicants;
452 ret = power_supply_register(&pdev->dev, &info->ac); 458 ret = power_supply_register(&pdev->dev, &info->ac);
453 if (ret) 459 if (ret)
454 goto out; 460 goto out;
@@ -459,6 +465,9 @@ static __devinit int max8925_power_probe(struct platform_device *pdev)
459 info->usb.properties = max8925_usb_props; 465 info->usb.properties = max8925_usb_props;
460 info->usb.num_properties = ARRAY_SIZE(max8925_usb_props); 466 info->usb.num_properties = ARRAY_SIZE(max8925_usb_props);
461 info->usb.get_property = max8925_usb_get_prop; 467 info->usb.get_property = max8925_usb_get_prop;
468 info->usb.supplied_to = pdata->supplied_to;
469 info->usb.num_supplicants = pdata->num_supplicants;
470
462 ret = power_supply_register(&pdev->dev, &info->usb); 471 ret = power_supply_register(&pdev->dev, &info->usb);
463 if (ret) 472 if (ret)
464 goto out_usb; 473 goto out_usb;
@@ -478,6 +487,8 @@ static __devinit int max8925_power_probe(struct platform_device *pdev)
478 info->topoff_threshold = pdata->topoff_threshold; 487 info->topoff_threshold = pdata->topoff_threshold;
479 info->fast_charge = pdata->fast_charge; 488 info->fast_charge = pdata->fast_charge;
480 info->set_charger = pdata->set_charger; 489 info->set_charger = pdata->set_charger;
490 info->no_temp_support = pdata->no_temp_support;
491 info->no_insert_detect = pdata->no_insert_detect;
481 492
482 max8925_init_charger(chip, info); 493 max8925_init_charger(chip, info);
483 return 0; 494 return 0;
@@ -512,17 +523,7 @@ static struct platform_driver max8925_power_driver = {
512 }, 523 },
513}; 524};
514 525
515static int __init max8925_power_init(void) 526module_platform_driver(max8925_power_driver);
516{
517 return platform_driver_register(&max8925_power_driver);
518}
519module_init(max8925_power_init);
520
521static void __exit max8925_power_exit(void)
522{
523 platform_driver_unregister(&max8925_power_driver);
524}
525module_exit(max8925_power_exit);
526 527
527MODULE_LICENSE("GPL"); 528MODULE_LICENSE("GPL");
528MODULE_DESCRIPTION("Power supply driver for MAX8925"); 529MODULE_DESCRIPTION("Power supply driver for MAX8925");
diff --git a/drivers/power/max8997_charger.c b/drivers/power/max8997_charger.c
index a23317d75c5..6e88c5d026b 100644
--- a/drivers/power/max8997_charger.c
+++ b/drivers/power/max8997_charger.c
@@ -19,7 +19,6 @@
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */ 20 */
21 21
22#include <linux/module.h>
23#include <linux/err.h> 22#include <linux/err.h>
24#include <linux/module.h> 23#include <linux/module.h>
25#include <linux/slab.h> 24#include <linux/slab.h>
@@ -98,7 +97,7 @@ static __devinit int max8997_battery_probe(struct platform_device *pdev)
98 return -EINVAL; 97 return -EINVAL;
99 98
100 if (pdata->eoc_mA) { 99 if (pdata->eoc_mA) {
101 u8 val = (pdata->eoc_mA - 50) / 10; 100 int val = (pdata->eoc_mA - 50) / 10;
102 if (val < 0) 101 if (val < 0)
103 val = 0; 102 val = 0;
104 if (val > 0xf) 103 if (val > 0xf)
@@ -179,6 +178,7 @@ static int __devexit max8997_battery_remove(struct platform_device *pdev)
179 178
180static const struct platform_device_id max8997_battery_id[] = { 179static const struct platform_device_id max8997_battery_id[] = {
181 { "max8997-battery", 0 }, 180 { "max8997-battery", 0 },
181 { }
182}; 182};
183 183
184static struct platform_driver max8997_battery_driver = { 184static struct platform_driver max8997_battery_driver = {
diff --git a/drivers/power/max8998_charger.c b/drivers/power/max8998_charger.c
index 93e3bb47a3a..9b3f2bf56e7 100644
--- a/drivers/power/max8998_charger.c
+++ b/drivers/power/max8998_charger.c
@@ -154,6 +154,7 @@ static __devinit int max8998_battery_probe(struct platform_device *pdev)
154 case 0: 154 case 0:
155 dev_dbg(max8998->dev, 155 dev_dbg(max8998->dev,
156 "Full Timeout not set: leave it unchanged.\n"); 156 "Full Timeout not set: leave it unchanged.\n");
157 break;
157 default: 158 default:
158 dev_err(max8998->dev, "Invalid Full Timeout value\n"); 159 dev_err(max8998->dev, "Invalid Full Timeout value\n");
159 ret = -EINVAL; 160 ret = -EINVAL;
@@ -190,6 +191,7 @@ static int __devexit max8998_battery_remove(struct platform_device *pdev)
190 191
191static const struct platform_device_id max8998_battery_id[] = { 192static const struct platform_device_id max8998_battery_id[] = {
192 { "max8998-battery", TYPE_MAX8998 }, 193 { "max8998-battery", TYPE_MAX8998 },
194 { }
193}; 195};
194 196
195static struct platform_driver max8998_battery_driver = { 197static struct platform_driver max8998_battery_driver = {
@@ -202,17 +204,7 @@ static struct platform_driver max8998_battery_driver = {
202 .id_table = max8998_battery_id, 204 .id_table = max8998_battery_id,
203}; 205};
204 206
205static int __init max8998_battery_init(void) 207module_platform_driver(max8998_battery_driver);
206{
207 return platform_driver_register(&max8998_battery_driver);
208}
209module_init(max8998_battery_init);
210
211static void __exit max8998_battery_cleanup(void)
212{
213 platform_driver_unregister(&max8998_battery_driver);
214}
215module_exit(max8998_battery_cleanup);
216 208
217MODULE_DESCRIPTION("MAXIM 8998 battery control driver"); 209MODULE_DESCRIPTION("MAXIM 8998 battery control driver");
218MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>"); 210MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
diff --git a/drivers/power/olpc_battery.c b/drivers/power/olpc_battery.c
index 0b0ff3a936a..7385092f9bc 100644
--- a/drivers/power/olpc_battery.c
+++ b/drivers/power/olpc_battery.c
@@ -519,29 +519,35 @@ static struct device_attribute olpc_bat_error = {
519 * Initialisation 519 * Initialisation
520 *********************************************************************/ 520 *********************************************************************/
521 521
522static struct platform_device *bat_pdev;
523
524static struct power_supply olpc_bat = { 522static struct power_supply olpc_bat = {
523 .name = "olpc-battery",
525 .get_property = olpc_bat_get_property, 524 .get_property = olpc_bat_get_property,
526 .use_for_apm = 1, 525 .use_for_apm = 1,
527}; 526};
528 527
529void olpc_battery_trigger_uevent(unsigned long cause) 528static int olpc_battery_suspend(struct platform_device *pdev,
529 pm_message_t state)
530{ 530{
531 if (cause & EC_SCI_SRC_ACPWR) 531 if (device_may_wakeup(olpc_ac.dev))
532 kobject_uevent(&olpc_ac.dev->kobj, KOBJ_CHANGE); 532 olpc_ec_wakeup_set(EC_SCI_SRC_ACPWR);
533 if (cause & (EC_SCI_SRC_BATERR|EC_SCI_SRC_BATSOC|EC_SCI_SRC_BATTERY)) 533 else
534 kobject_uevent(&olpc_bat.dev->kobj, KOBJ_CHANGE); 534 olpc_ec_wakeup_clear(EC_SCI_SRC_ACPWR);
535
536 if (device_may_wakeup(olpc_bat.dev))
537 olpc_ec_wakeup_set(EC_SCI_SRC_BATTERY | EC_SCI_SRC_BATSOC
538 | EC_SCI_SRC_BATERR);
539 else
540 olpc_ec_wakeup_clear(EC_SCI_SRC_BATTERY | EC_SCI_SRC_BATSOC
541 | EC_SCI_SRC_BATERR);
542
543 return 0;
535} 544}
536 545
537static int __init olpc_bat_init(void) 546static int __devinit olpc_battery_probe(struct platform_device *pdev)
538{ 547{
539 int ret = 0; 548 int ret;
540 uint8_t status; 549 uint8_t status;
541 550
542 if (!olpc_platform_info.ecver)
543 return -ENXIO;
544
545 /* 551 /*
546 * We've seen a number of EC protocol changes; this driver requires 552 * We've seen a number of EC protocol changes; this driver requires
547 * the latest EC protocol, supported by 0x44 and above. 553 * the latest EC protocol, supported by 0x44 and above.
@@ -558,15 +564,10 @@ static int __init olpc_bat_init(void)
558 564
559 /* Ignore the status. It doesn't actually matter */ 565 /* Ignore the status. It doesn't actually matter */
560 566
561 bat_pdev = platform_device_register_simple("olpc-battery", 0, NULL, 0); 567 ret = power_supply_register(&pdev->dev, &olpc_ac);
562 if (IS_ERR(bat_pdev))
563 return PTR_ERR(bat_pdev);
564
565 ret = power_supply_register(&bat_pdev->dev, &olpc_ac);
566 if (ret) 568 if (ret)
567 goto ac_failed; 569 return ret;
568 570
569 olpc_bat.name = bat_pdev->name;
570 if (olpc_board_at_least(olpc_board_pre(0xd0))) { /* XO-1.5 */ 571 if (olpc_board_at_least(olpc_board_pre(0xd0))) { /* XO-1.5 */
571 olpc_bat.properties = olpc_xo15_bat_props; 572 olpc_bat.properties = olpc_xo15_bat_props;
572 olpc_bat.num_properties = ARRAY_SIZE(olpc_xo15_bat_props); 573 olpc_bat.num_properties = ARRAY_SIZE(olpc_xo15_bat_props);
@@ -575,7 +576,7 @@ static int __init olpc_bat_init(void)
575 olpc_bat.num_properties = ARRAY_SIZE(olpc_xo1_bat_props); 576 olpc_bat.num_properties = ARRAY_SIZE(olpc_xo1_bat_props);
576 } 577 }
577 578
578 ret = power_supply_register(&bat_pdev->dev, &olpc_bat); 579 ret = power_supply_register(&pdev->dev, &olpc_bat);
579 if (ret) 580 if (ret)
580 goto battery_failed; 581 goto battery_failed;
581 582
@@ -587,7 +588,12 @@ static int __init olpc_bat_init(void)
587 if (ret) 588 if (ret)
588 goto error_failed; 589 goto error_failed;
589 590
590 goto success; 591 if (olpc_ec_wakeup_available()) {
592 device_set_wakeup_capable(olpc_ac.dev, true);
593 device_set_wakeup_capable(olpc_bat.dev, true);
594 }
595
596 return 0;
591 597
592error_failed: 598error_failed:
593 device_remove_bin_file(olpc_bat.dev, &olpc_bat_eeprom); 599 device_remove_bin_file(olpc_bat.dev, &olpc_bat_eeprom);
@@ -595,23 +601,36 @@ eeprom_failed:
595 power_supply_unregister(&olpc_bat); 601 power_supply_unregister(&olpc_bat);
596battery_failed: 602battery_failed:
597 power_supply_unregister(&olpc_ac); 603 power_supply_unregister(&olpc_ac);
598ac_failed:
599 platform_device_unregister(bat_pdev);
600success:
601 return ret; 604 return ret;
602} 605}
603 606
604static void __exit olpc_bat_exit(void) 607static int __devexit olpc_battery_remove(struct platform_device *pdev)
605{ 608{
606 device_remove_file(olpc_bat.dev, &olpc_bat_error); 609 device_remove_file(olpc_bat.dev, &olpc_bat_error);
607 device_remove_bin_file(olpc_bat.dev, &olpc_bat_eeprom); 610 device_remove_bin_file(olpc_bat.dev, &olpc_bat_eeprom);
608 power_supply_unregister(&olpc_bat); 611 power_supply_unregister(&olpc_bat);
609 power_supply_unregister(&olpc_ac); 612 power_supply_unregister(&olpc_ac);
610 platform_device_unregister(bat_pdev); 613 return 0;
611} 614}
612 615
613module_init(olpc_bat_init); 616static const struct of_device_id olpc_battery_ids[] __devinitconst = {
614module_exit(olpc_bat_exit); 617 { .compatible = "olpc,xo1-battery" },
618 {}
619};
620MODULE_DEVICE_TABLE(of, olpc_battery_ids);
621
622static struct platform_driver olpc_battery_driver = {
623 .driver = {
624 .name = "olpc-battery",
625 .owner = THIS_MODULE,
626 .of_match_table = olpc_battery_ids,
627 },
628 .probe = olpc_battery_probe,
629 .remove = __devexit_p(olpc_battery_remove),
630 .suspend = olpc_battery_suspend,
631};
632
633module_platform_driver(olpc_battery_driver);
615 634
616MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); 635MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
617MODULE_LICENSE("GPL"); 636MODULE_LICENSE("GPL");
diff --git a/drivers/power/pcf50633-charger.c b/drivers/power/pcf50633-charger.c
index 4fa52e1781a..3d1e9efb6f5 100644
--- a/drivers/power/pcf50633-charger.c
+++ b/drivers/power/pcf50633-charger.c
@@ -474,17 +474,7 @@ static struct platform_driver pcf50633_mbc_driver = {
474 .remove = __devexit_p(pcf50633_mbc_remove), 474 .remove = __devexit_p(pcf50633_mbc_remove),
475}; 475};
476 476
477static int __init pcf50633_mbc_init(void) 477module_platform_driver(pcf50633_mbc_driver);
478{
479 return platform_driver_register(&pcf50633_mbc_driver);
480}
481module_init(pcf50633_mbc_init);
482
483static void __exit pcf50633_mbc_exit(void)
484{
485 platform_driver_unregister(&pcf50633_mbc_driver);
486}
487module_exit(pcf50633_mbc_exit);
488 478
489MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>"); 479MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
490MODULE_DESCRIPTION("PCF50633 mbc driver"); 480MODULE_DESCRIPTION("PCF50633 mbc driver");
diff --git a/drivers/power/pda_power.c b/drivers/power/pda_power.c
index 69f8aa3a6a4..fd49689738a 100644
--- a/drivers/power/pda_power.c
+++ b/drivers/power/pda_power.c
@@ -14,6 +14,7 @@
14#include <linux/platform_device.h> 14#include <linux/platform_device.h>
15#include <linux/err.h> 15#include <linux/err.h>
16#include <linux/interrupt.h> 16#include <linux/interrupt.h>
17#include <linux/notifier.h>
17#include <linux/power_supply.h> 18#include <linux/power_supply.h>
18#include <linux/pda_power.h> 19#include <linux/pda_power.h>
19#include <linux/regulator/consumer.h> 20#include <linux/regulator/consumer.h>
@@ -40,7 +41,9 @@ static int polling;
40 41
41#ifdef CONFIG_USB_OTG_UTILS 42#ifdef CONFIG_USB_OTG_UTILS
42static struct otg_transceiver *transceiver; 43static struct otg_transceiver *transceiver;
44static struct notifier_block otg_nb;
43#endif 45#endif
46
44static struct regulator *ac_draw; 47static struct regulator *ac_draw;
45 48
46enum { 49enum {
@@ -222,7 +225,42 @@ static void polling_timer_func(unsigned long unused)
222#ifdef CONFIG_USB_OTG_UTILS 225#ifdef CONFIG_USB_OTG_UTILS
223static int otg_is_usb_online(void) 226static int otg_is_usb_online(void)
224{ 227{
225 return (transceiver->state == OTG_STATE_B_PERIPHERAL); 228 return (transceiver->last_event == USB_EVENT_VBUS ||
229 transceiver->last_event == USB_EVENT_ENUMERATED);
230}
231
232static int otg_is_ac_online(void)
233{
234 return (transceiver->last_event == USB_EVENT_CHARGER);
235}
236
237static int otg_handle_notification(struct notifier_block *nb,
238 unsigned long event, void *unused)
239{
240 switch (event) {
241 case USB_EVENT_CHARGER:
242 ac_status = PDA_PSY_TO_CHANGE;
243 break;
244 case USB_EVENT_VBUS:
245 case USB_EVENT_ENUMERATED:
246 usb_status = PDA_PSY_TO_CHANGE;
247 break;
248 case USB_EVENT_NONE:
249 ac_status = PDA_PSY_TO_CHANGE;
250 usb_status = PDA_PSY_TO_CHANGE;
251 break;
252 default:
253 return NOTIFY_OK;
254 }
255
256 /*
257 * Wait a bit before reading ac/usb line status and setting charger,
258 * because ac/usb status readings may lag from irq.
259 */
260 mod_timer(&charger_timer,
261 jiffies + msecs_to_jiffies(pdata->wait_for_status));
262
263 return NOTIFY_OK;
226} 264}
227#endif 265#endif
228 266
@@ -282,6 +320,16 @@ static int pda_power_probe(struct platform_device *pdev)
282 ret = PTR_ERR(ac_draw); 320 ret = PTR_ERR(ac_draw);
283 } 321 }
284 322
323#ifdef CONFIG_USB_OTG_UTILS
324 transceiver = otg_get_transceiver();
325 if (transceiver && !pdata->is_usb_online) {
326 pdata->is_usb_online = otg_is_usb_online;
327 }
328 if (transceiver && !pdata->is_ac_online) {
329 pdata->is_ac_online = otg_is_ac_online;
330 }
331#endif
332
285 if (pdata->is_ac_online) { 333 if (pdata->is_ac_online) {
286 ret = power_supply_register(&pdev->dev, &pda_psy_ac); 334 ret = power_supply_register(&pdev->dev, &pda_psy_ac);
287 if (ret) { 335 if (ret) {
@@ -303,13 +351,6 @@ static int pda_power_probe(struct platform_device *pdev)
303 } 351 }
304 } 352 }
305 353
306#ifdef CONFIG_USB_OTG_UTILS
307 transceiver = otg_get_transceiver();
308 if (transceiver && !pdata->is_usb_online) {
309 pdata->is_usb_online = otg_is_usb_online;
310 }
311#endif
312
313 if (pdata->is_usb_online) { 354 if (pdata->is_usb_online) {
314 ret = power_supply_register(&pdev->dev, &pda_psy_usb); 355 ret = power_supply_register(&pdev->dev, &pda_psy_usb);
315 if (ret) { 356 if (ret) {
@@ -331,6 +372,18 @@ static int pda_power_probe(struct platform_device *pdev)
331 } 372 }
332 } 373 }
333 374
375#ifdef CONFIG_USB_OTG_UTILS
376 if (transceiver && pdata->use_otg_notifier) {
377 otg_nb.notifier_call = otg_handle_notification;
378 ret = otg_register_notifier(transceiver, &otg_nb);
379 if (ret) {
380 dev_err(dev, "failure to register otg notifier\n");
381 goto otg_reg_notifier_failed;
382 }
383 polling = 0;
384 }
385#endif
386
334 if (polling) { 387 if (polling) {
335 dev_dbg(dev, "will poll for status\n"); 388 dev_dbg(dev, "will poll for status\n");
336 setup_timer(&polling_timer, polling_timer_func, 0); 389 setup_timer(&polling_timer, polling_timer_func, 0);
@@ -343,6 +396,11 @@ static int pda_power_probe(struct platform_device *pdev)
343 396
344 return 0; 397 return 0;
345 398
399#ifdef CONFIG_USB_OTG_UTILS
400otg_reg_notifier_failed:
401 if (pdata->is_usb_online && usb_irq)
402 free_irq(usb_irq->start, &pda_psy_usb);
403#endif
346usb_irq_failed: 404usb_irq_failed:
347 if (pdata->is_usb_online) 405 if (pdata->is_usb_online)
348 power_supply_unregister(&pda_psy_usb); 406 power_supply_unregister(&pda_psy_usb);
@@ -440,8 +498,6 @@ static int pda_power_resume(struct platform_device *pdev)
440#define pda_power_resume NULL 498#define pda_power_resume NULL
441#endif /* CONFIG_PM */ 499#endif /* CONFIG_PM */
442 500
443MODULE_ALIAS("platform:pda-power");
444
445static struct platform_driver pda_power_pdrv = { 501static struct platform_driver pda_power_pdrv = {
446 .driver = { 502 .driver = {
447 .name = "pda-power", 503 .name = "pda-power",
@@ -452,17 +508,8 @@ static struct platform_driver pda_power_pdrv = {
452 .resume = pda_power_resume, 508 .resume = pda_power_resume,
453}; 509};
454 510
455static int __init pda_power_init(void) 511module_platform_driver(pda_power_pdrv);
456{
457 return platform_driver_register(&pda_power_pdrv);
458}
459 512
460static void __exit pda_power_exit(void)
461{
462 platform_driver_unregister(&pda_power_pdrv);
463}
464
465module_init(pda_power_init);
466module_exit(pda_power_exit);
467MODULE_LICENSE("GPL"); 513MODULE_LICENSE("GPL");
468MODULE_AUTHOR("Anton Vorontsov <cbou@mail.ru>"); 514MODULE_AUTHOR("Anton Vorontsov <cbou@mail.ru>");
515MODULE_ALIAS("platform:pda-power");
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index 329b46b2327..6ad61272678 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -98,7 +98,9 @@ static int __power_supply_is_system_supplied(struct device *dev, void *data)
98{ 98{
99 union power_supply_propval ret = {0,}; 99 union power_supply_propval ret = {0,};
100 struct power_supply *psy = dev_get_drvdata(dev); 100 struct power_supply *psy = dev_get_drvdata(dev);
101 unsigned int *count = data;
101 102
103 (*count)++;
102 if (psy->type != POWER_SUPPLY_TYPE_BATTERY) { 104 if (psy->type != POWER_SUPPLY_TYPE_BATTERY) {
103 if (psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &ret)) 105 if (psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &ret))
104 return 0; 106 return 0;
@@ -111,10 +113,18 @@ static int __power_supply_is_system_supplied(struct device *dev, void *data)
111int power_supply_is_system_supplied(void) 113int power_supply_is_system_supplied(void)
112{ 114{
113 int error; 115 int error;
116 unsigned int count = 0;
114 117
115 error = class_for_each_device(power_supply_class, NULL, NULL, 118 error = class_for_each_device(power_supply_class, NULL, &count,
116 __power_supply_is_system_supplied); 119 __power_supply_is_system_supplied);
117 120
121 /*
122 * If no power class device was found at all, most probably we are
123 * running on a desktop system, so assume we are on mains power.
124 */
125 if (count == 0)
126 return 1;
127
118 return error; 128 return error;
119} 129}
120EXPORT_SYMBOL_GPL(power_supply_is_system_supplied); 130EXPORT_SYMBOL_GPL(power_supply_is_system_supplied);
@@ -147,6 +157,12 @@ struct power_supply *power_supply_get_by_name(char *name)
147} 157}
148EXPORT_SYMBOL_GPL(power_supply_get_by_name); 158EXPORT_SYMBOL_GPL(power_supply_get_by_name);
149 159
160int power_supply_powers(struct power_supply *psy, struct device *dev)
161{
162 return sysfs_create_link(&psy->dev->kobj, &dev->kobj, "powers");
163}
164EXPORT_SYMBOL_GPL(power_supply_powers);
165
150static void power_supply_dev_release(struct device *dev) 166static void power_supply_dev_release(struct device *dev)
151{ 167{
152 pr_debug("device: '%s': %s\n", dev_name(dev), __func__); 168 pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
@@ -202,6 +218,7 @@ EXPORT_SYMBOL_GPL(power_supply_register);
202void power_supply_unregister(struct power_supply *psy) 218void power_supply_unregister(struct power_supply *psy)
203{ 219{
204 cancel_work_sync(&psy->changed_work); 220 cancel_work_sync(&psy->changed_work);
221 sysfs_remove_link(&psy->dev->kobj, "powers");
205 power_supply_remove_triggers(psy); 222 power_supply_remove_triggers(psy);
206 device_unregister(psy->dev); 223 device_unregister(psy->dev);
207} 224}
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
index e95cd657dac..b52b57ca308 100644
--- a/drivers/power/power_supply_sysfs.c
+++ b/drivers/power/power_supply_sysfs.c
@@ -43,7 +43,7 @@ static ssize_t power_supply_show_property(struct device *dev,
43 struct device_attribute *attr, 43 struct device_attribute *attr,
44 char *buf) { 44 char *buf) {
45 static char *type_text[] = { 45 static char *type_text[] = {
46 "Battery", "UPS", "Mains", "USB", 46 "Unknown", "Battery", "UPS", "Mains", "USB",
47 "USB_DCP", "USB_CDP", "USB_ACA" 47 "USB_DCP", "USB_CDP", "USB_ACA"
48 }; 48 };
49 static char *status_text[] = { 49 static char *status_text[] = {
@@ -63,6 +63,9 @@ static ssize_t power_supply_show_property(struct device *dev,
63 static char *capacity_level_text[] = { 63 static char *capacity_level_text[] = {
64 "Unknown", "Critical", "Low", "Normal", "High", "Full" 64 "Unknown", "Critical", "Low", "Normal", "High", "Full"
65 }; 65 };
66 static char *scope_text[] = {
67 "Unknown", "System", "Device"
68 };
66 ssize_t ret = 0; 69 ssize_t ret = 0;
67 struct power_supply *psy = dev_get_drvdata(dev); 70 struct power_supply *psy = dev_get_drvdata(dev);
68 const ptrdiff_t off = attr - power_supply_attrs; 71 const ptrdiff_t off = attr - power_supply_attrs;
@@ -78,8 +81,8 @@ static ssize_t power_supply_show_property(struct device *dev,
78 dev_dbg(dev, "driver has no data for `%s' property\n", 81 dev_dbg(dev, "driver has no data for `%s' property\n",
79 attr->attr.name); 82 attr->attr.name);
80 else if (ret != -ENODEV) 83 else if (ret != -ENODEV)
81 dev_err(dev, "driver failed to report `%s' property\n", 84 dev_err(dev, "driver failed to report `%s' property: %zd\n",
82 attr->attr.name); 85 attr->attr.name, ret);
83 return ret; 86 return ret;
84 } 87 }
85 88
@@ -95,6 +98,8 @@ static ssize_t power_supply_show_property(struct device *dev,
95 return sprintf(buf, "%s\n", capacity_level_text[value.intval]); 98 return sprintf(buf, "%s\n", capacity_level_text[value.intval]);
96 else if (off == POWER_SUPPLY_PROP_TYPE) 99 else if (off == POWER_SUPPLY_PROP_TYPE)
97 return sprintf(buf, "%s\n", type_text[value.intval]); 100 return sprintf(buf, "%s\n", type_text[value.intval]);
101 else if (off == POWER_SUPPLY_PROP_SCOPE)
102 return sprintf(buf, "%s\n", scope_text[value.intval]);
98 else if (off >= POWER_SUPPLY_PROP_MODEL_NAME) 103 else if (off >= POWER_SUPPLY_PROP_MODEL_NAME)
99 return sprintf(buf, "%s\n", value.strval); 104 return sprintf(buf, "%s\n", value.strval);
100 105
@@ -167,6 +172,7 @@ static struct device_attribute power_supply_attrs[] = {
167 POWER_SUPPLY_ATTR(time_to_full_now), 172 POWER_SUPPLY_ATTR(time_to_full_now),
168 POWER_SUPPLY_ATTR(time_to_full_avg), 173 POWER_SUPPLY_ATTR(time_to_full_avg),
169 POWER_SUPPLY_ATTR(type), 174 POWER_SUPPLY_ATTR(type),
175 POWER_SUPPLY_ATTR(scope),
170 /* Properties of type `const char *' */ 176 /* Properties of type `const char *' */
171 POWER_SUPPLY_ATTR(model_name), 177 POWER_SUPPLY_ATTR(model_name),
172 POWER_SUPPLY_ATTR(manufacturer), 178 POWER_SUPPLY_ATTR(manufacturer),
diff --git a/drivers/power/s3c_adc_battery.c b/drivers/power/s3c_adc_battery.c
index d32d0d70f9b..8b804a56675 100644
--- a/drivers/power/s3c_adc_battery.c
+++ b/drivers/power/s3c_adc_battery.c
@@ -47,6 +47,22 @@ static void s3c_adc_bat_ext_power_changed(struct power_supply *psy)
47 msecs_to_jiffies(JITTER_DELAY)); 47 msecs_to_jiffies(JITTER_DELAY));
48} 48}
49 49
50static int gather_samples(struct s3c_adc_client *client, int num, int channel)
51{
52 int value, i;
53
54 /* default to 1 if nothing is set */
55 if (num < 1)
56 num = 1;
57
58 value = 0;
59 for (i = 0; i < num; i++)
60 value += s3c_adc_read(client, channel);
61 value /= num;
62
63 return value;
64}
65
50static enum power_supply_property s3c_adc_backup_bat_props[] = { 66static enum power_supply_property s3c_adc_backup_bat_props[] = {
51 POWER_SUPPLY_PROP_VOLTAGE_NOW, 67 POWER_SUPPLY_PROP_VOLTAGE_NOW,
52 POWER_SUPPLY_PROP_VOLTAGE_MIN, 68 POWER_SUPPLY_PROP_VOLTAGE_MIN,
@@ -67,7 +83,8 @@ static int s3c_adc_backup_bat_get_property(struct power_supply *psy,
67 if (bat->volt_value < 0 || 83 if (bat->volt_value < 0 ||
68 jiffies_to_msecs(jiffies - bat->timestamp) > 84 jiffies_to_msecs(jiffies - bat->timestamp) >
69 BAT_POLL_INTERVAL) { 85 BAT_POLL_INTERVAL) {
70 bat->volt_value = s3c_adc_read(bat->client, 86 bat->volt_value = gather_samples(bat->client,
87 bat->pdata->backup_volt_samples,
71 bat->pdata->backup_volt_channel); 88 bat->pdata->backup_volt_channel);
72 bat->volt_value *= bat->pdata->backup_volt_mult; 89 bat->volt_value *= bat->pdata->backup_volt_mult;
73 bat->timestamp = jiffies; 90 bat->timestamp = jiffies;
@@ -139,9 +156,11 @@ static int s3c_adc_bat_get_property(struct power_supply *psy,
139 if (bat->volt_value < 0 || bat->cur_value < 0 || 156 if (bat->volt_value < 0 || bat->cur_value < 0 ||
140 jiffies_to_msecs(jiffies - bat->timestamp) > 157 jiffies_to_msecs(jiffies - bat->timestamp) >
141 BAT_POLL_INTERVAL) { 158 BAT_POLL_INTERVAL) {
142 bat->volt_value = s3c_adc_read(bat->client, 159 bat->volt_value = gather_samples(bat->client,
160 bat->pdata->volt_samples,
143 bat->pdata->volt_channel) * bat->pdata->volt_mult; 161 bat->pdata->volt_channel) * bat->pdata->volt_mult;
144 bat->cur_value = s3c_adc_read(bat->client, 162 bat->cur_value = gather_samples(bat->client,
163 bat->pdata->current_samples,
145 bat->pdata->current_channel) * bat->pdata->current_mult; 164 bat->pdata->current_channel) * bat->pdata->current_mult;
146 bat->timestamp = jiffies; 165 bat->timestamp = jiffies;
147 } 166 }
@@ -421,17 +440,7 @@ static struct platform_driver s3c_adc_bat_driver = {
421 .resume = s3c_adc_bat_resume, 440 .resume = s3c_adc_bat_resume,
422}; 441};
423 442
424static int __init s3c_adc_bat_init(void) 443module_platform_driver(s3c_adc_bat_driver);
425{
426 return platform_driver_register(&s3c_adc_bat_driver);
427}
428module_init(s3c_adc_bat_init);
429
430static void __exit s3c_adc_bat_exit(void)
431{
432 platform_driver_unregister(&s3c_adc_bat_driver);
433}
434module_exit(s3c_adc_bat_exit);
435 444
436MODULE_AUTHOR("Vasily Khoruzhick <anarsoul@gmail.com>"); 445MODULE_AUTHOR("Vasily Khoruzhick <anarsoul@gmail.com>");
437MODULE_DESCRIPTION("iPAQ H1930/H1940/RX1950 battery controller driver"); 446MODULE_DESCRIPTION("iPAQ H1930/H1940/RX1950 battery controller driver");
diff --git a/drivers/power/bq20z75.c b/drivers/power/sbs-battery.c
index 9c5e5beda3a..9ff8af069da 100644
--- a/drivers/power/bq20z75.c
+++ b/drivers/power/sbs-battery.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Gas Gauge driver for TI's BQ20Z75 2 * Gas Gauge driver for SBS Compliant Batteries
3 * 3 *
4 * Copyright (c) 2010, NVIDIA Corporation. 4 * Copyright (c) 2010, NVIDIA Corporation.
5 * 5 *
@@ -28,7 +28,7 @@
28#include <linux/interrupt.h> 28#include <linux/interrupt.h>
29#include <linux/gpio.h> 29#include <linux/gpio.h>
30 30
31#include <linux/power/bq20z75.h> 31#include <linux/power/sbs-battery.h>
32 32
33enum { 33enum {
34 REG_MANUFACTURER_DATA, 34 REG_MANUFACTURER_DATA,
@@ -53,7 +53,7 @@ enum {
53/* Battery Mode defines */ 53/* Battery Mode defines */
54#define BATTERY_MODE_OFFSET 0x03 54#define BATTERY_MODE_OFFSET 0x03
55#define BATTERY_MODE_MASK 0x8000 55#define BATTERY_MODE_MASK 0x8000
56enum bq20z75_battery_mode { 56enum sbs_battery_mode {
57 BATTERY_MODE_AMPS, 57 BATTERY_MODE_AMPS,
58 BATTERY_MODE_WATTS 58 BATTERY_MODE_WATTS
59}; 59};
@@ -67,62 +67,56 @@ enum bq20z75_battery_mode {
67#define BATTERY_FULL_CHARGED 0x20 67#define BATTERY_FULL_CHARGED 0x20
68#define BATTERY_FULL_DISCHARGED 0x10 68#define BATTERY_FULL_DISCHARGED 0x10
69 69
70#define BQ20Z75_DATA(_psp, _addr, _min_value, _max_value) { \ 70#define SBS_DATA(_psp, _addr, _min_value, _max_value) { \
71 .psp = _psp, \ 71 .psp = _psp, \
72 .addr = _addr, \ 72 .addr = _addr, \
73 .min_value = _min_value, \ 73 .min_value = _min_value, \
74 .max_value = _max_value, \ 74 .max_value = _max_value, \
75} 75}
76 76
77static const struct bq20z75_device_data { 77static const struct chip_data {
78 enum power_supply_property psp; 78 enum power_supply_property psp;
79 u8 addr; 79 u8 addr;
80 int min_value; 80 int min_value;
81 int max_value; 81 int max_value;
82} bq20z75_data[] = { 82} sbs_data[] = {
83 [REG_MANUFACTURER_DATA] = 83 [REG_MANUFACTURER_DATA] =
84 BQ20Z75_DATA(POWER_SUPPLY_PROP_PRESENT, 0x00, 0, 65535), 84 SBS_DATA(POWER_SUPPLY_PROP_PRESENT, 0x00, 0, 65535),
85 [REG_TEMPERATURE] = 85 [REG_TEMPERATURE] =
86 BQ20Z75_DATA(POWER_SUPPLY_PROP_TEMP, 0x08, 0, 65535), 86 SBS_DATA(POWER_SUPPLY_PROP_TEMP, 0x08, 0, 65535),
87 [REG_VOLTAGE] = 87 [REG_VOLTAGE] =
88 BQ20Z75_DATA(POWER_SUPPLY_PROP_VOLTAGE_NOW, 0x09, 0, 20000), 88 SBS_DATA(POWER_SUPPLY_PROP_VOLTAGE_NOW, 0x09, 0, 20000),
89 [REG_CURRENT] = 89 [REG_CURRENT] =
90 BQ20Z75_DATA(POWER_SUPPLY_PROP_CURRENT_NOW, 0x0A, -32768, 90 SBS_DATA(POWER_SUPPLY_PROP_CURRENT_NOW, 0x0A, -32768, 32767),
91 32767),
92 [REG_CAPACITY] = 91 [REG_CAPACITY] =
93 BQ20Z75_DATA(POWER_SUPPLY_PROP_CAPACITY, 0x0E, 0, 100), 92 SBS_DATA(POWER_SUPPLY_PROP_CAPACITY, 0x0E, 0, 100),
94 [REG_REMAINING_CAPACITY] = 93 [REG_REMAINING_CAPACITY] =
95 BQ20Z75_DATA(POWER_SUPPLY_PROP_ENERGY_NOW, 0x0F, 0, 65535), 94 SBS_DATA(POWER_SUPPLY_PROP_ENERGY_NOW, 0x0F, 0, 65535),
96 [REG_REMAINING_CAPACITY_CHARGE] = 95 [REG_REMAINING_CAPACITY_CHARGE] =
97 BQ20Z75_DATA(POWER_SUPPLY_PROP_CHARGE_NOW, 0x0F, 0, 65535), 96 SBS_DATA(POWER_SUPPLY_PROP_CHARGE_NOW, 0x0F, 0, 65535),
98 [REG_FULL_CHARGE_CAPACITY] = 97 [REG_FULL_CHARGE_CAPACITY] =
99 BQ20Z75_DATA(POWER_SUPPLY_PROP_ENERGY_FULL, 0x10, 0, 65535), 98 SBS_DATA(POWER_SUPPLY_PROP_ENERGY_FULL, 0x10, 0, 65535),
100 [REG_FULL_CHARGE_CAPACITY_CHARGE] = 99 [REG_FULL_CHARGE_CAPACITY_CHARGE] =
101 BQ20Z75_DATA(POWER_SUPPLY_PROP_CHARGE_FULL, 0x10, 0, 65535), 100 SBS_DATA(POWER_SUPPLY_PROP_CHARGE_FULL, 0x10, 0, 65535),
102 [REG_TIME_TO_EMPTY] = 101 [REG_TIME_TO_EMPTY] =
103 BQ20Z75_DATA(POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, 0x12, 0, 102 SBS_DATA(POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, 0x12, 0, 65535),
104 65535),
105 [REG_TIME_TO_FULL] = 103 [REG_TIME_TO_FULL] =
106 BQ20Z75_DATA(POWER_SUPPLY_PROP_TIME_TO_FULL_AVG, 0x13, 0, 104 SBS_DATA(POWER_SUPPLY_PROP_TIME_TO_FULL_AVG, 0x13, 0, 65535),
107 65535),
108 [REG_STATUS] = 105 [REG_STATUS] =
109 BQ20Z75_DATA(POWER_SUPPLY_PROP_STATUS, 0x16, 0, 65535), 106 SBS_DATA(POWER_SUPPLY_PROP_STATUS, 0x16, 0, 65535),
110 [REG_CYCLE_COUNT] = 107 [REG_CYCLE_COUNT] =
111 BQ20Z75_DATA(POWER_SUPPLY_PROP_CYCLE_COUNT, 0x17, 0, 65535), 108 SBS_DATA(POWER_SUPPLY_PROP_CYCLE_COUNT, 0x17, 0, 65535),
112 [REG_DESIGN_CAPACITY] = 109 [REG_DESIGN_CAPACITY] =
113 BQ20Z75_DATA(POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, 0x18, 0, 110 SBS_DATA(POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, 0x18, 0, 65535),
114 65535),
115 [REG_DESIGN_CAPACITY_CHARGE] = 111 [REG_DESIGN_CAPACITY_CHARGE] =
116 BQ20Z75_DATA(POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 0x18, 0, 112 SBS_DATA(POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 0x18, 0, 65535),
117 65535),
118 [REG_DESIGN_VOLTAGE] = 113 [REG_DESIGN_VOLTAGE] =
119 BQ20Z75_DATA(POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, 0x19, 0, 114 SBS_DATA(POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, 0x19, 0, 65535),
120 65535),
121 [REG_SERIAL_NUMBER] = 115 [REG_SERIAL_NUMBER] =
122 BQ20Z75_DATA(POWER_SUPPLY_PROP_SERIAL_NUMBER, 0x1C, 0, 65535), 116 SBS_DATA(POWER_SUPPLY_PROP_SERIAL_NUMBER, 0x1C, 0, 65535),
123}; 117};
124 118
125static enum power_supply_property bq20z75_properties[] = { 119static enum power_supply_property sbs_properties[] = {
126 POWER_SUPPLY_PROP_STATUS, 120 POWER_SUPPLY_PROP_STATUS,
127 POWER_SUPPLY_PROP_HEALTH, 121 POWER_SUPPLY_PROP_HEALTH,
128 POWER_SUPPLY_PROP_PRESENT, 122 POWER_SUPPLY_PROP_PRESENT,
@@ -144,10 +138,10 @@ static enum power_supply_property bq20z75_properties[] = {
144 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 138 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
145}; 139};
146 140
147struct bq20z75_info { 141struct sbs_info {
148 struct i2c_client *client; 142 struct i2c_client *client;
149 struct power_supply power_supply; 143 struct power_supply power_supply;
150 struct bq20z75_platform_data *pdata; 144 struct sbs_platform_data *pdata;
151 bool is_present; 145 bool is_present;
152 bool gpio_detect; 146 bool gpio_detect;
153 bool enable_detection; 147 bool enable_detection;
@@ -158,14 +152,14 @@ struct bq20z75_info {
158 int ignore_changes; 152 int ignore_changes;
159}; 153};
160 154
161static int bq20z75_read_word_data(struct i2c_client *client, u8 address) 155static int sbs_read_word_data(struct i2c_client *client, u8 address)
162{ 156{
163 struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client); 157 struct sbs_info *chip = i2c_get_clientdata(client);
164 s32 ret = 0; 158 s32 ret = 0;
165 int retries = 1; 159 int retries = 1;
166 160
167 if (bq20z75_device->pdata) 161 if (chip->pdata)
168 retries = max(bq20z75_device->pdata->i2c_retry_count + 1, 1); 162 retries = max(chip->pdata->i2c_retry_count + 1, 1);
169 163
170 while (retries > 0) { 164 while (retries > 0) {
171 ret = i2c_smbus_read_word_data(client, address); 165 ret = i2c_smbus_read_word_data(client, address);
@@ -184,15 +178,15 @@ static int bq20z75_read_word_data(struct i2c_client *client, u8 address)
184 return le16_to_cpu(ret); 178 return le16_to_cpu(ret);
185} 179}
186 180
187static int bq20z75_write_word_data(struct i2c_client *client, u8 address, 181static int sbs_write_word_data(struct i2c_client *client, u8 address,
188 u16 value) 182 u16 value)
189{ 183{
190 struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client); 184 struct sbs_info *chip = i2c_get_clientdata(client);
191 s32 ret = 0; 185 s32 ret = 0;
192 int retries = 1; 186 int retries = 1;
193 187
194 if (bq20z75_device->pdata) 188 if (chip->pdata)
195 retries = max(bq20z75_device->pdata->i2c_retry_count + 1, 1); 189 retries = max(chip->pdata->i2c_retry_count + 1, 1);
196 190
197 while (retries > 0) { 191 while (retries > 0) {
198 ret = i2c_smbus_write_word_data(client, address, 192 ret = i2c_smbus_write_word_data(client, address,
@@ -212,44 +206,41 @@ static int bq20z75_write_word_data(struct i2c_client *client, u8 address,
212 return 0; 206 return 0;
213} 207}
214 208
215static int bq20z75_get_battery_presence_and_health( 209static int sbs_get_battery_presence_and_health(
216 struct i2c_client *client, enum power_supply_property psp, 210 struct i2c_client *client, enum power_supply_property psp,
217 union power_supply_propval *val) 211 union power_supply_propval *val)
218{ 212{
219 s32 ret; 213 s32 ret;
220 struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client); 214 struct sbs_info *chip = i2c_get_clientdata(client);
221 215
222 if (psp == POWER_SUPPLY_PROP_PRESENT && 216 if (psp == POWER_SUPPLY_PROP_PRESENT &&
223 bq20z75_device->gpio_detect) { 217 chip->gpio_detect) {
224 ret = gpio_get_value( 218 ret = gpio_get_value(chip->pdata->battery_detect);
225 bq20z75_device->pdata->battery_detect); 219 if (ret == chip->pdata->battery_detect_present)
226 if (ret == bq20z75_device->pdata->battery_detect_present)
227 val->intval = 1; 220 val->intval = 1;
228 else 221 else
229 val->intval = 0; 222 val->intval = 0;
230 bq20z75_device->is_present = val->intval; 223 chip->is_present = val->intval;
231 return ret; 224 return ret;
232 } 225 }
233 226
234 /* Write to ManufacturerAccess with 227 /* Write to ManufacturerAccess with
235 * ManufacturerAccess command and then 228 * ManufacturerAccess command and then
236 * read the status */ 229 * read the status */
237 ret = bq20z75_write_word_data(client, 230 ret = sbs_write_word_data(client, sbs_data[REG_MANUFACTURER_DATA].addr,
238 bq20z75_data[REG_MANUFACTURER_DATA].addr, 231 MANUFACTURER_ACCESS_STATUS);
239 MANUFACTURER_ACCESS_STATUS);
240 if (ret < 0) { 232 if (ret < 0) {
241 if (psp == POWER_SUPPLY_PROP_PRESENT) 233 if (psp == POWER_SUPPLY_PROP_PRESENT)
242 val->intval = 0; /* battery removed */ 234 val->intval = 0; /* battery removed */
243 return ret; 235 return ret;
244 } 236 }
245 237
246 ret = bq20z75_read_word_data(client, 238 ret = sbs_read_word_data(client, sbs_data[REG_MANUFACTURER_DATA].addr);
247 bq20z75_data[REG_MANUFACTURER_DATA].addr);
248 if (ret < 0) 239 if (ret < 0)
249 return ret; 240 return ret;
250 241
251 if (ret < bq20z75_data[REG_MANUFACTURER_DATA].min_value || 242 if (ret < sbs_data[REG_MANUFACTURER_DATA].min_value ||
252 ret > bq20z75_data[REG_MANUFACTURER_DATA].max_value) { 243 ret > sbs_data[REG_MANUFACTURER_DATA].max_value) {
253 val->intval = 0; 244 val->intval = 0;
254 return 0; 245 return 0;
255 } 246 }
@@ -279,24 +270,23 @@ static int bq20z75_get_battery_presence_and_health(
279 return 0; 270 return 0;
280} 271}
281 272
282static int bq20z75_get_battery_property(struct i2c_client *client, 273static int sbs_get_battery_property(struct i2c_client *client,
283 int reg_offset, enum power_supply_property psp, 274 int reg_offset, enum power_supply_property psp,
284 union power_supply_propval *val) 275 union power_supply_propval *val)
285{ 276{
286 struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client); 277 struct sbs_info *chip = i2c_get_clientdata(client);
287 s32 ret; 278 s32 ret;
288 279
289 ret = bq20z75_read_word_data(client, 280 ret = sbs_read_word_data(client, sbs_data[reg_offset].addr);
290 bq20z75_data[reg_offset].addr);
291 if (ret < 0) 281 if (ret < 0)
292 return ret; 282 return ret;
293 283
294 /* returned values are 16 bit */ 284 /* returned values are 16 bit */
295 if (bq20z75_data[reg_offset].min_value < 0) 285 if (sbs_data[reg_offset].min_value < 0)
296 ret = (s16)ret; 286 ret = (s16)ret;
297 287
298 if (ret >= bq20z75_data[reg_offset].min_value && 288 if (ret >= sbs_data[reg_offset].min_value &&
299 ret <= bq20z75_data[reg_offset].max_value) { 289 ret <= sbs_data[reg_offset].max_value) {
300 val->intval = ret; 290 val->intval = ret;
301 if (psp != POWER_SUPPLY_PROP_STATUS) 291 if (psp != POWER_SUPPLY_PROP_STATUS)
302 return 0; 292 return 0;
@@ -310,12 +300,12 @@ static int bq20z75_get_battery_property(struct i2c_client *client,
310 else 300 else
311 val->intval = POWER_SUPPLY_STATUS_CHARGING; 301 val->intval = POWER_SUPPLY_STATUS_CHARGING;
312 302
313 if (bq20z75_device->poll_time == 0) 303 if (chip->poll_time == 0)
314 bq20z75_device->last_state = val->intval; 304 chip->last_state = val->intval;
315 else if (bq20z75_device->last_state != val->intval) { 305 else if (chip->last_state != val->intval) {
316 cancel_delayed_work_sync(&bq20z75_device->work); 306 cancel_delayed_work_sync(&chip->work);
317 power_supply_changed(&bq20z75_device->power_supply); 307 power_supply_changed(&chip->power_supply);
318 bq20z75_device->poll_time = 0; 308 chip->poll_time = 0;
319 } 309 }
320 } else { 310 } else {
321 if (psp == POWER_SUPPLY_PROP_STATUS) 311 if (psp == POWER_SUPPLY_PROP_STATUS)
@@ -327,7 +317,7 @@ static int bq20z75_get_battery_property(struct i2c_client *client,
327 return 0; 317 return 0;
328} 318}
329 319
330static void bq20z75_unit_adjustment(struct i2c_client *client, 320static void sbs_unit_adjustment(struct i2c_client *client,
331 enum power_supply_property psp, union power_supply_propval *val) 321 enum power_supply_property psp, union power_supply_propval *val)
332{ 322{
333#define BASE_UNIT_CONVERSION 1000 323#define BASE_UNIT_CONVERSION 1000
@@ -338,7 +328,7 @@ static void bq20z75_unit_adjustment(struct i2c_client *client,
338 case POWER_SUPPLY_PROP_ENERGY_NOW: 328 case POWER_SUPPLY_PROP_ENERGY_NOW:
339 case POWER_SUPPLY_PROP_ENERGY_FULL: 329 case POWER_SUPPLY_PROP_ENERGY_FULL:
340 case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: 330 case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
341 /* bq20z75 provides energy in units of 10mWh. 331 /* sbs provides energy in units of 10mWh.
342 * Convert to µWh 332 * Convert to µWh
343 */ 333 */
344 val->intval *= BATTERY_MODE_CAP_MULT_WATT; 334 val->intval *= BATTERY_MODE_CAP_MULT_WATT;
@@ -354,7 +344,7 @@ static void bq20z75_unit_adjustment(struct i2c_client *client,
354 break; 344 break;
355 345
356 case POWER_SUPPLY_PROP_TEMP: 346 case POWER_SUPPLY_PROP_TEMP:
357 /* bq20z75 provides battery temperature in 0.1K 347 /* sbs provides battery temperature in 0.1K
358 * so convert it to 0.1°C 348 * so convert it to 0.1°C
359 */ 349 */
360 val->intval -= TEMP_KELVIN_TO_CELSIUS; 350 val->intval -= TEMP_KELVIN_TO_CELSIUS;
@@ -362,7 +352,7 @@ static void bq20z75_unit_adjustment(struct i2c_client *client,
362 352
363 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: 353 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
364 case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG: 354 case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG:
365 /* bq20z75 provides time to empty and time to full in minutes. 355 /* sbs provides time to empty and time to full in minutes.
366 * Convert to seconds 356 * Convert to seconds
367 */ 357 */
368 val->intval *= TIME_UNIT_CONVERSION; 358 val->intval *= TIME_UNIT_CONVERSION;
@@ -374,13 +364,12 @@ static void bq20z75_unit_adjustment(struct i2c_client *client,
374 } 364 }
375} 365}
376 366
377static enum bq20z75_battery_mode 367static enum sbs_battery_mode sbs_set_battery_mode(struct i2c_client *client,
378bq20z75_set_battery_mode(struct i2c_client *client, 368 enum sbs_battery_mode mode)
379 enum bq20z75_battery_mode mode)
380{ 369{
381 int ret, original_val; 370 int ret, original_val;
382 371
383 original_val = bq20z75_read_word_data(client, BATTERY_MODE_OFFSET); 372 original_val = sbs_read_word_data(client, BATTERY_MODE_OFFSET);
384 if (original_val < 0) 373 if (original_val < 0)
385 return original_val; 374 return original_val;
386 375
@@ -392,68 +381,67 @@ bq20z75_set_battery_mode(struct i2c_client *client,
392 else 381 else
393 ret = original_val | BATTERY_MODE_MASK; 382 ret = original_val | BATTERY_MODE_MASK;
394 383
395 ret = bq20z75_write_word_data(client, BATTERY_MODE_OFFSET, ret); 384 ret = sbs_write_word_data(client, BATTERY_MODE_OFFSET, ret);
396 if (ret < 0) 385 if (ret < 0)
397 return ret; 386 return ret;
398 387
399 return original_val & BATTERY_MODE_MASK; 388 return original_val & BATTERY_MODE_MASK;
400} 389}
401 390
402static int bq20z75_get_battery_capacity(struct i2c_client *client, 391static int sbs_get_battery_capacity(struct i2c_client *client,
403 int reg_offset, enum power_supply_property psp, 392 int reg_offset, enum power_supply_property psp,
404 union power_supply_propval *val) 393 union power_supply_propval *val)
405{ 394{
406 s32 ret; 395 s32 ret;
407 enum bq20z75_battery_mode mode = BATTERY_MODE_WATTS; 396 enum sbs_battery_mode mode = BATTERY_MODE_WATTS;
408 397
409 if (power_supply_is_amp_property(psp)) 398 if (power_supply_is_amp_property(psp))
410 mode = BATTERY_MODE_AMPS; 399 mode = BATTERY_MODE_AMPS;
411 400
412 mode = bq20z75_set_battery_mode(client, mode); 401 mode = sbs_set_battery_mode(client, mode);
413 if (mode < 0) 402 if (mode < 0)
414 return mode; 403 return mode;
415 404
416 ret = bq20z75_read_word_data(client, bq20z75_data[reg_offset].addr); 405 ret = sbs_read_word_data(client, sbs_data[reg_offset].addr);
417 if (ret < 0) 406 if (ret < 0)
418 return ret; 407 return ret;
419 408
420 if (psp == POWER_SUPPLY_PROP_CAPACITY) { 409 if (psp == POWER_SUPPLY_PROP_CAPACITY) {
421 /* bq20z75 spec says that this can be >100 % 410 /* sbs spec says that this can be >100 %
422 * even if max value is 100 % */ 411 * even if max value is 100 % */
423 val->intval = min(ret, 100); 412 val->intval = min(ret, 100);
424 } else 413 } else
425 val->intval = ret; 414 val->intval = ret;
426 415
427 ret = bq20z75_set_battery_mode(client, mode); 416 ret = sbs_set_battery_mode(client, mode);
428 if (ret < 0) 417 if (ret < 0)
429 return ret; 418 return ret;
430 419
431 return 0; 420 return 0;
432} 421}
433 422
434static char bq20z75_serial[5]; 423static char sbs_serial[5];
435static int bq20z75_get_battery_serial_number(struct i2c_client *client, 424static int sbs_get_battery_serial_number(struct i2c_client *client,
436 union power_supply_propval *val) 425 union power_supply_propval *val)
437{ 426{
438 int ret; 427 int ret;
439 428
440 ret = bq20z75_read_word_data(client, 429 ret = sbs_read_word_data(client, sbs_data[REG_SERIAL_NUMBER].addr);
441 bq20z75_data[REG_SERIAL_NUMBER].addr);
442 if (ret < 0) 430 if (ret < 0)
443 return ret; 431 return ret;
444 432
445 ret = sprintf(bq20z75_serial, "%04x", ret); 433 ret = sprintf(sbs_serial, "%04x", ret);
446 val->strval = bq20z75_serial; 434 val->strval = sbs_serial;
447 435
448 return 0; 436 return 0;
449} 437}
450 438
451static int bq20z75_get_property_index(struct i2c_client *client, 439static int sbs_get_property_index(struct i2c_client *client,
452 enum power_supply_property psp) 440 enum power_supply_property psp)
453{ 441{
454 int count; 442 int count;
455 for (count = 0; count < ARRAY_SIZE(bq20z75_data); count++) 443 for (count = 0; count < ARRAY_SIZE(sbs_data); count++)
456 if (psp == bq20z75_data[count].psp) 444 if (psp == sbs_data[count].psp)
457 return count; 445 return count;
458 446
459 dev_warn(&client->dev, 447 dev_warn(&client->dev,
@@ -462,19 +450,19 @@ static int bq20z75_get_property_index(struct i2c_client *client,
462 return -EINVAL; 450 return -EINVAL;
463} 451}
464 452
465static int bq20z75_get_property(struct power_supply *psy, 453static int sbs_get_property(struct power_supply *psy,
466 enum power_supply_property psp, 454 enum power_supply_property psp,
467 union power_supply_propval *val) 455 union power_supply_propval *val)
468{ 456{
469 int ret = 0; 457 int ret = 0;
470 struct bq20z75_info *bq20z75_device = container_of(psy, 458 struct sbs_info *chip = container_of(psy,
471 struct bq20z75_info, power_supply); 459 struct sbs_info, power_supply);
472 struct i2c_client *client = bq20z75_device->client; 460 struct i2c_client *client = chip->client;
473 461
474 switch (psp) { 462 switch (psp) {
475 case POWER_SUPPLY_PROP_PRESENT: 463 case POWER_SUPPLY_PROP_PRESENT:
476 case POWER_SUPPLY_PROP_HEALTH: 464 case POWER_SUPPLY_PROP_HEALTH:
477 ret = bq20z75_get_battery_presence_and_health(client, psp, val); 465 ret = sbs_get_battery_presence_and_health(client, psp, val);
478 if (psp == POWER_SUPPLY_PROP_PRESENT) 466 if (psp == POWER_SUPPLY_PROP_PRESENT)
479 return 0; 467 return 0;
480 break; 468 break;
@@ -490,15 +478,15 @@ static int bq20z75_get_property(struct power_supply *psy,
490 case POWER_SUPPLY_PROP_CHARGE_FULL: 478 case POWER_SUPPLY_PROP_CHARGE_FULL:
491 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: 479 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
492 case POWER_SUPPLY_PROP_CAPACITY: 480 case POWER_SUPPLY_PROP_CAPACITY:
493 ret = bq20z75_get_property_index(client, psp); 481 ret = sbs_get_property_index(client, psp);
494 if (ret < 0) 482 if (ret < 0)
495 break; 483 break;
496 484
497 ret = bq20z75_get_battery_capacity(client, ret, psp, val); 485 ret = sbs_get_battery_capacity(client, ret, psp, val);
498 break; 486 break;
499 487
500 case POWER_SUPPLY_PROP_SERIAL_NUMBER: 488 case POWER_SUPPLY_PROP_SERIAL_NUMBER:
501 ret = bq20z75_get_battery_serial_number(client, val); 489 ret = sbs_get_battery_serial_number(client, val);
502 break; 490 break;
503 491
504 case POWER_SUPPLY_PROP_STATUS: 492 case POWER_SUPPLY_PROP_STATUS:
@@ -509,11 +497,11 @@ static int bq20z75_get_property(struct power_supply *psy,
509 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: 497 case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
510 case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG: 498 case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG:
511 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: 499 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
512 ret = bq20z75_get_property_index(client, psp); 500 ret = sbs_get_property_index(client, psp);
513 if (ret < 0) 501 if (ret < 0)
514 break; 502 break;
515 503
516 ret = bq20z75_get_battery_property(client, ret, psp, val); 504 ret = sbs_get_battery_property(client, ret, psp, val);
517 break; 505 break;
518 506
519 default: 507 default:
@@ -522,25 +510,25 @@ static int bq20z75_get_property(struct power_supply *psy,
522 return -EINVAL; 510 return -EINVAL;
523 } 511 }
524 512
525 if (!bq20z75_device->enable_detection) 513 if (!chip->enable_detection)
526 goto done; 514 goto done;
527 515
528 if (!bq20z75_device->gpio_detect && 516 if (!chip->gpio_detect &&
529 bq20z75_device->is_present != (ret >= 0)) { 517 chip->is_present != (ret >= 0)) {
530 bq20z75_device->is_present = (ret >= 0); 518 chip->is_present = (ret >= 0);
531 power_supply_changed(&bq20z75_device->power_supply); 519 power_supply_changed(&chip->power_supply);
532 } 520 }
533 521
534done: 522done:
535 if (!ret) { 523 if (!ret) {
536 /* Convert units to match requirements for power supply class */ 524 /* Convert units to match requirements for power supply class */
537 bq20z75_unit_adjustment(client, psp, val); 525 sbs_unit_adjustment(client, psp, val);
538 } 526 }
539 527
540 dev_dbg(&client->dev, 528 dev_dbg(&client->dev,
541 "%s: property = %d, value = %x\n", __func__, psp, val->intval); 529 "%s: property = %d, value = %x\n", __func__, psp, val->intval);
542 530
543 if (ret && bq20z75_device->is_present) 531 if (ret && chip->is_present)
544 return ret; 532 return ret;
545 533
546 /* battery not present, so return NODATA for properties */ 534 /* battery not present, so return NODATA for properties */
@@ -550,7 +538,7 @@ done:
550 return 0; 538 return 0;
551} 539}
552 540
553static irqreturn_t bq20z75_irq(int irq, void *devid) 541static irqreturn_t sbs_irq(int irq, void *devid)
554{ 542{
555 struct power_supply *battery = devid; 543 struct power_supply *battery = devid;
556 544
@@ -559,36 +547,35 @@ static irqreturn_t bq20z75_irq(int irq, void *devid)
559 return IRQ_HANDLED; 547 return IRQ_HANDLED;
560} 548}
561 549
562static void bq20z75_external_power_changed(struct power_supply *psy) 550static void sbs_external_power_changed(struct power_supply *psy)
563{ 551{
564 struct bq20z75_info *bq20z75_device; 552 struct sbs_info *chip;
565 553
566 bq20z75_device = container_of(psy, struct bq20z75_info, power_supply); 554 chip = container_of(psy, struct sbs_info, power_supply);
567 555
568 if (bq20z75_device->ignore_changes > 0) { 556 if (chip->ignore_changes > 0) {
569 bq20z75_device->ignore_changes--; 557 chip->ignore_changes--;
570 return; 558 return;
571 } 559 }
572 560
573 /* cancel outstanding work */ 561 /* cancel outstanding work */
574 cancel_delayed_work_sync(&bq20z75_device->work); 562 cancel_delayed_work_sync(&chip->work);
575 563
576 schedule_delayed_work(&bq20z75_device->work, HZ); 564 schedule_delayed_work(&chip->work, HZ);
577 bq20z75_device->poll_time = bq20z75_device->pdata->poll_retry_count; 565 chip->poll_time = chip->pdata->poll_retry_count;
578} 566}
579 567
580static void bq20z75_delayed_work(struct work_struct *work) 568static void sbs_delayed_work(struct work_struct *work)
581{ 569{
582 struct bq20z75_info *bq20z75_device; 570 struct sbs_info *chip;
583 s32 ret; 571 s32 ret;
584 572
585 bq20z75_device = container_of(work, struct bq20z75_info, work.work); 573 chip = container_of(work, struct sbs_info, work.work);
586 574
587 ret = bq20z75_read_word_data(bq20z75_device->client, 575 ret = sbs_read_word_data(chip->client, sbs_data[REG_STATUS].addr);
588 bq20z75_data[REG_STATUS].addr);
589 /* if the read failed, give up on this work */ 576 /* if the read failed, give up on this work */
590 if (ret < 0) { 577 if (ret < 0) {
591 bq20z75_device->poll_time = 0; 578 chip->poll_time = 0;
592 return; 579 return;
593 } 580 }
594 581
@@ -601,62 +588,145 @@ static void bq20z75_delayed_work(struct work_struct *work)
601 else 588 else
602 ret = POWER_SUPPLY_STATUS_CHARGING; 589 ret = POWER_SUPPLY_STATUS_CHARGING;
603 590
604 if (bq20z75_device->last_state != ret) { 591 if (chip->last_state != ret) {
605 bq20z75_device->poll_time = 0; 592 chip->poll_time = 0;
606 power_supply_changed(&bq20z75_device->power_supply); 593 power_supply_changed(&chip->power_supply);
607 return; 594 return;
608 } 595 }
609 if (bq20z75_device->poll_time > 0) { 596 if (chip->poll_time > 0) {
610 schedule_delayed_work(&bq20z75_device->work, HZ); 597 schedule_delayed_work(&chip->work, HZ);
611 bq20z75_device->poll_time--; 598 chip->poll_time--;
612 return; 599 return;
613 } 600 }
614} 601}
615 602
616static int __devinit bq20z75_probe(struct i2c_client *client, 603#if defined(CONFIG_OF)
604
605#include <linux/of_device.h>
606#include <linux/of_gpio.h>
607
608static const struct of_device_id sbs_dt_ids[] = {
609 { .compatible = "sbs,sbs-battery" },
610 { .compatible = "ti,bq20z75" },
611 { }
612};
613MODULE_DEVICE_TABLE(of, sbs_dt_ids);
614
615static struct sbs_platform_data *sbs_of_populate_pdata(
616 struct i2c_client *client)
617{
618 struct device_node *of_node = client->dev.of_node;
619 struct sbs_platform_data *pdata = client->dev.platform_data;
620 enum of_gpio_flags gpio_flags;
621 int rc;
622 u32 prop;
623
624 /* verify this driver matches this device */
625 if (!of_node)
626 return NULL;
627
628 /* if platform data is set, honor it */
629 if (pdata)
630 return pdata;
631
632 /* first make sure at least one property is set, otherwise
633 * it won't change behavior from running without pdata.
634 */
635 if (!of_get_property(of_node, "sbs,i2c-retry-count", NULL) &&
636 !of_get_property(of_node, "sbs,poll-retry-count", NULL) &&
637 !of_get_property(of_node, "sbs,battery-detect-gpios", NULL))
638 goto of_out;
639
640 pdata = devm_kzalloc(&client->dev, sizeof(struct sbs_platform_data),
641 GFP_KERNEL);
642 if (!pdata)
643 goto of_out;
644
645 rc = of_property_read_u32(of_node, "sbs,i2c-retry-count", &prop);
646 if (!rc)
647 pdata->i2c_retry_count = prop;
648
649 rc = of_property_read_u32(of_node, "sbs,poll-retry-count", &prop);
650 if (!rc)
651 pdata->poll_retry_count = prop;
652
653 if (!of_get_property(of_node, "sbs,battery-detect-gpios", NULL)) {
654 pdata->battery_detect = -1;
655 goto of_out;
656 }
657
658 pdata->battery_detect = of_get_named_gpio_flags(of_node,
659 "sbs,battery-detect-gpios", 0, &gpio_flags);
660
661 if (gpio_flags & OF_GPIO_ACTIVE_LOW)
662 pdata->battery_detect_present = 0;
663 else
664 pdata->battery_detect_present = 1;
665
666of_out:
667 return pdata;
668}
669#else
670#define sbs_dt_ids NULL
671static struct sbs_platform_data *sbs_of_populate_pdata(
672 struct i2c_client *client)
673{
674 return client->dev.platform_data;
675}
676#endif
677
678static int __devinit sbs_probe(struct i2c_client *client,
617 const struct i2c_device_id *id) 679 const struct i2c_device_id *id)
618{ 680{
619 struct bq20z75_info *bq20z75_device; 681 struct sbs_info *chip;
620 struct bq20z75_platform_data *pdata = client->dev.platform_data; 682 struct sbs_platform_data *pdata = client->dev.platform_data;
621 int rc; 683 int rc;
622 int irq; 684 int irq;
685 char *name;
623 686
624 bq20z75_device = kzalloc(sizeof(struct bq20z75_info), GFP_KERNEL); 687 name = kasprintf(GFP_KERNEL, "sbs-%s", dev_name(&client->dev));
625 if (!bq20z75_device) 688 if (!name) {
689 dev_err(&client->dev, "Failed to allocate device name\n");
626 return -ENOMEM; 690 return -ENOMEM;
691 }
692
693 chip = kzalloc(sizeof(struct sbs_info), GFP_KERNEL);
694 if (!chip) {
695 rc = -ENOMEM;
696 goto exit_free_name;
697 }
627 698
628 bq20z75_device->client = client; 699 chip->client = client;
629 bq20z75_device->enable_detection = false; 700 chip->enable_detection = false;
630 bq20z75_device->gpio_detect = false; 701 chip->gpio_detect = false;
631 bq20z75_device->power_supply.name = "battery"; 702 chip->power_supply.name = name;
632 bq20z75_device->power_supply.type = POWER_SUPPLY_TYPE_BATTERY; 703 chip->power_supply.type = POWER_SUPPLY_TYPE_BATTERY;
633 bq20z75_device->power_supply.properties = bq20z75_properties; 704 chip->power_supply.properties = sbs_properties;
634 bq20z75_device->power_supply.num_properties = 705 chip->power_supply.num_properties = ARRAY_SIZE(sbs_properties);
635 ARRAY_SIZE(bq20z75_properties); 706 chip->power_supply.get_property = sbs_get_property;
636 bq20z75_device->power_supply.get_property = bq20z75_get_property;
637 /* ignore first notification of external change, it is generated 707 /* ignore first notification of external change, it is generated
638 * from the power_supply_register call back 708 * from the power_supply_register call back
639 */ 709 */
640 bq20z75_device->ignore_changes = 1; 710 chip->ignore_changes = 1;
641 bq20z75_device->last_state = POWER_SUPPLY_STATUS_UNKNOWN; 711 chip->last_state = POWER_SUPPLY_STATUS_UNKNOWN;
642 bq20z75_device->power_supply.external_power_changed = 712 chip->power_supply.external_power_changed = sbs_external_power_changed;
643 bq20z75_external_power_changed; 713
714 pdata = sbs_of_populate_pdata(client);
644 715
645 if (pdata) { 716 if (pdata) {
646 bq20z75_device->gpio_detect = 717 chip->gpio_detect = gpio_is_valid(pdata->battery_detect);
647 gpio_is_valid(pdata->battery_detect); 718 chip->pdata = pdata;
648 bq20z75_device->pdata = pdata;
649 } 719 }
650 720
651 i2c_set_clientdata(client, bq20z75_device); 721 i2c_set_clientdata(client, chip);
652 722
653 if (!bq20z75_device->gpio_detect) 723 if (!chip->gpio_detect)
654 goto skip_gpio; 724 goto skip_gpio;
655 725
656 rc = gpio_request(pdata->battery_detect, dev_name(&client->dev)); 726 rc = gpio_request(pdata->battery_detect, dev_name(&client->dev));
657 if (rc) { 727 if (rc) {
658 dev_warn(&client->dev, "Failed to request gpio: %d\n", rc); 728 dev_warn(&client->dev, "Failed to request gpio: %d\n", rc);
659 bq20z75_device->gpio_detect = false; 729 chip->gpio_detect = false;
660 goto skip_gpio; 730 goto skip_gpio;
661 } 731 }
662 732
@@ -664,7 +734,7 @@ static int __devinit bq20z75_probe(struct i2c_client *client,
664 if (rc) { 734 if (rc) {
665 dev_warn(&client->dev, "Failed to get gpio as input: %d\n", rc); 735 dev_warn(&client->dev, "Failed to get gpio as input: %d\n", rc);
666 gpio_free(pdata->battery_detect); 736 gpio_free(pdata->battery_detect);
667 bq20z75_device->gpio_detect = false; 737 chip->gpio_detect = false;
668 goto skip_gpio; 738 goto skip_gpio;
669 } 739 }
670 740
@@ -672,25 +742,25 @@ static int __devinit bq20z75_probe(struct i2c_client *client,
672 if (irq <= 0) { 742 if (irq <= 0) {
673 dev_warn(&client->dev, "Failed to get gpio as irq: %d\n", irq); 743 dev_warn(&client->dev, "Failed to get gpio as irq: %d\n", irq);
674 gpio_free(pdata->battery_detect); 744 gpio_free(pdata->battery_detect);
675 bq20z75_device->gpio_detect = false; 745 chip->gpio_detect = false;
676 goto skip_gpio; 746 goto skip_gpio;
677 } 747 }
678 748
679 rc = request_irq(irq, bq20z75_irq, 749 rc = request_irq(irq, sbs_irq,
680 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 750 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
681 dev_name(&client->dev), &bq20z75_device->power_supply); 751 dev_name(&client->dev), &chip->power_supply);
682 if (rc) { 752 if (rc) {
683 dev_warn(&client->dev, "Failed to request irq: %d\n", rc); 753 dev_warn(&client->dev, "Failed to request irq: %d\n", rc);
684 gpio_free(pdata->battery_detect); 754 gpio_free(pdata->battery_detect);
685 bq20z75_device->gpio_detect = false; 755 chip->gpio_detect = false;
686 goto skip_gpio; 756 goto skip_gpio;
687 } 757 }
688 758
689 bq20z75_device->irq = irq; 759 chip->irq = irq;
690 760
691skip_gpio: 761skip_gpio:
692 762
693 rc = power_supply_register(&client->dev, &bq20z75_device->power_supply); 763 rc = power_supply_register(&client->dev, &chip->power_supply);
694 if (rc) { 764 if (rc) {
695 dev_err(&client->dev, 765 dev_err(&client->dev,
696 "%s: Failed to register power supply\n", __func__); 766 "%s: Failed to register power supply\n", __func__);
@@ -700,95 +770,100 @@ skip_gpio:
700 dev_info(&client->dev, 770 dev_info(&client->dev,
701 "%s: battery gas gauge device registered\n", client->name); 771 "%s: battery gas gauge device registered\n", client->name);
702 772
703 INIT_DELAYED_WORK(&bq20z75_device->work, bq20z75_delayed_work); 773 INIT_DELAYED_WORK(&chip->work, sbs_delayed_work);
704 774
705 bq20z75_device->enable_detection = true; 775 chip->enable_detection = true;
706 776
707 return 0; 777 return 0;
708 778
709exit_psupply: 779exit_psupply:
710 if (bq20z75_device->irq) 780 if (chip->irq)
711 free_irq(bq20z75_device->irq, &bq20z75_device->power_supply); 781 free_irq(chip->irq, &chip->power_supply);
712 if (bq20z75_device->gpio_detect) 782 if (chip->gpio_detect)
713 gpio_free(pdata->battery_detect); 783 gpio_free(pdata->battery_detect);
714 784
715 kfree(bq20z75_device); 785 kfree(chip);
786
787exit_free_name:
788 kfree(name);
716 789
717 return rc; 790 return rc;
718} 791}
719 792
720static int __devexit bq20z75_remove(struct i2c_client *client) 793static int __devexit sbs_remove(struct i2c_client *client)
721{ 794{
722 struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client); 795 struct sbs_info *chip = i2c_get_clientdata(client);
723 796
724 if (bq20z75_device->irq) 797 if (chip->irq)
725 free_irq(bq20z75_device->irq, &bq20z75_device->power_supply); 798 free_irq(chip->irq, &chip->power_supply);
726 if (bq20z75_device->gpio_detect) 799 if (chip->gpio_detect)
727 gpio_free(bq20z75_device->pdata->battery_detect); 800 gpio_free(chip->pdata->battery_detect);
728 801
729 power_supply_unregister(&bq20z75_device->power_supply); 802 power_supply_unregister(&chip->power_supply);
730 803
731 cancel_delayed_work_sync(&bq20z75_device->work); 804 cancel_delayed_work_sync(&chip->work);
732 805
733 kfree(bq20z75_device); 806 kfree(chip->power_supply.name);
734 bq20z75_device = NULL; 807 kfree(chip);
808 chip = NULL;
735 809
736 return 0; 810 return 0;
737} 811}
738 812
739#if defined CONFIG_PM 813#if defined CONFIG_PM
740static int bq20z75_suspend(struct i2c_client *client, 814static int sbs_suspend(struct i2c_client *client,
741 pm_message_t state) 815 pm_message_t state)
742{ 816{
743 struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client); 817 struct sbs_info *chip = i2c_get_clientdata(client);
744 s32 ret; 818 s32 ret;
745 819
746 if (bq20z75_device->poll_time > 0) 820 if (chip->poll_time > 0)
747 cancel_delayed_work_sync(&bq20z75_device->work); 821 cancel_delayed_work_sync(&chip->work);
748 822
749 /* write to manufacturer access with sleep command */ 823 /* write to manufacturer access with sleep command */
750 ret = bq20z75_write_word_data(client, 824 ret = sbs_write_word_data(client, sbs_data[REG_MANUFACTURER_DATA].addr,
751 bq20z75_data[REG_MANUFACTURER_DATA].addr,
752 MANUFACTURER_ACCESS_SLEEP); 825 MANUFACTURER_ACCESS_SLEEP);
753 if (bq20z75_device->is_present && ret < 0) 826 if (chip->is_present && ret < 0)
754 return ret; 827 return ret;
755 828
756 return 0; 829 return 0;
757} 830}
758#else 831#else
759#define bq20z75_suspend NULL 832#define sbs_suspend NULL
760#endif 833#endif
761/* any smbus transaction will wake up bq20z75 */ 834/* any smbus transaction will wake up sbs */
762#define bq20z75_resume NULL 835#define sbs_resume NULL
763 836
764static const struct i2c_device_id bq20z75_id[] = { 837static const struct i2c_device_id sbs_id[] = {
765 { "bq20z75", 0 }, 838 { "bq20z75", 0 },
839 { "sbs-battery", 1 },
766 {} 840 {}
767}; 841};
768MODULE_DEVICE_TABLE(i2c, bq20z75_id); 842MODULE_DEVICE_TABLE(i2c, sbs_id);
769 843
770static struct i2c_driver bq20z75_battery_driver = { 844static struct i2c_driver sbs_battery_driver = {
771 .probe = bq20z75_probe, 845 .probe = sbs_probe,
772 .remove = __devexit_p(bq20z75_remove), 846 .remove = __devexit_p(sbs_remove),
773 .suspend = bq20z75_suspend, 847 .suspend = sbs_suspend,
774 .resume = bq20z75_resume, 848 .resume = sbs_resume,
775 .id_table = bq20z75_id, 849 .id_table = sbs_id,
776 .driver = { 850 .driver = {
777 .name = "bq20z75-battery", 851 .name = "sbs-battery",
852 .of_match_table = sbs_dt_ids,
778 }, 853 },
779}; 854};
780 855
781static int __init bq20z75_battery_init(void) 856static int __init sbs_battery_init(void)
782{ 857{
783 return i2c_add_driver(&bq20z75_battery_driver); 858 return i2c_add_driver(&sbs_battery_driver);
784} 859}
785module_init(bq20z75_battery_init); 860module_init(sbs_battery_init);
786 861
787static void __exit bq20z75_battery_exit(void) 862static void __exit sbs_battery_exit(void)
788{ 863{
789 i2c_del_driver(&bq20z75_battery_driver); 864 i2c_del_driver(&sbs_battery_driver);
790} 865}
791module_exit(bq20z75_battery_exit); 866module_exit(sbs_battery_exit);
792 867
793MODULE_DESCRIPTION("BQ20z75 battery monitor driver"); 868MODULE_DESCRIPTION("SBS battery monitor driver");
794MODULE_LICENSE("GPL"); 869MODULE_LICENSE("GPL");
diff --git a/drivers/power/tosa_battery.c b/drivers/power/tosa_battery.c
index 53f0d3524fc..28bbe7e094e 100644
--- a/drivers/power/tosa_battery.c
+++ b/drivers/power/tosa_battery.c
@@ -307,25 +307,20 @@ static struct tosa_bat tosa_bat_bu = {
307 .adc_temp_divider = -1, 307 .adc_temp_divider = -1,
308}; 308};
309 309
310static struct { 310static struct gpio tosa_bat_gpios[] = {
311 int gpio; 311 { TOSA_GPIO_CHARGE_OFF, GPIOF_OUT_INIT_HIGH, "main charge off" },
312 char *name; 312 { TOSA_GPIO_CHARGE_OFF_JC, GPIOF_OUT_INIT_HIGH, "jacket charge off" },
313 bool output; 313 { TOSA_GPIO_BAT_SW_ON, GPIOF_OUT_INIT_LOW, "battery switch" },
314 int value; 314 { TOSA_GPIO_BAT0_V_ON, GPIOF_OUT_INIT_LOW, "main battery" },
315} gpios[] = { 315 { TOSA_GPIO_BAT1_V_ON, GPIOF_OUT_INIT_LOW, "jacket battery" },
316 { TOSA_GPIO_CHARGE_OFF, "main charge off", 1, 1 }, 316 { TOSA_GPIO_BAT1_TH_ON, GPIOF_OUT_INIT_LOW, "main battery temp" },
317 { TOSA_GPIO_CHARGE_OFF_JC, "jacket charge off", 1, 1 }, 317 { TOSA_GPIO_BAT0_TH_ON, GPIOF_OUT_INIT_LOW, "jacket battery temp" },
318 { TOSA_GPIO_BAT_SW_ON, "battery switch", 1, 0 }, 318 { TOSA_GPIO_BU_CHRG_ON, GPIOF_OUT_INIT_LOW, "backup battery" },
319 { TOSA_GPIO_BAT0_V_ON, "main battery", 1, 0 }, 319 { TOSA_GPIO_BAT0_CRG, GPIOF_IN, "main battery full" },
320 { TOSA_GPIO_BAT1_V_ON, "jacket battery", 1, 0 }, 320 { TOSA_GPIO_BAT1_CRG, GPIOF_IN, "jacket battery full" },
321 { TOSA_GPIO_BAT1_TH_ON, "main battery temp", 1, 0 }, 321 { TOSA_GPIO_BAT0_LOW, GPIOF_IN, "main battery low" },
322 { TOSA_GPIO_BAT0_TH_ON, "jacket battery temp", 1, 0 }, 322 { TOSA_GPIO_BAT1_LOW, GPIOF_IN, "jacket battery low" },
323 { TOSA_GPIO_BU_CHRG_ON, "backup battery", 1, 0 }, 323 { TOSA_GPIO_JACKET_DETECT, GPIOF_IN, "jacket detect" },
324 { TOSA_GPIO_BAT0_CRG, "main battery full", 0, 0 },
325 { TOSA_GPIO_BAT1_CRG, "jacket battery full", 0, 0 },
326 { TOSA_GPIO_BAT0_LOW, "main battery low", 0, 0 },
327 { TOSA_GPIO_BAT1_LOW, "jacket battery low", 0, 0 },
328 { TOSA_GPIO_JACKET_DETECT, "jacket detect", 0, 0 },
329}; 324};
330 325
331#ifdef CONFIG_PM 326#ifdef CONFIG_PM
@@ -350,27 +345,13 @@ static int tosa_bat_resume(struct platform_device *dev)
350static int __devinit tosa_bat_probe(struct platform_device *dev) 345static int __devinit tosa_bat_probe(struct platform_device *dev)
351{ 346{
352 int ret; 347 int ret;
353 int i;
354 348
355 if (!machine_is_tosa()) 349 if (!machine_is_tosa())
356 return -ENODEV; 350 return -ENODEV;
357 351
358 for (i = 0; i < ARRAY_SIZE(gpios); i++) { 352 ret = gpio_request_array(tosa_bat_gpios, ARRAY_SIZE(tosa_bat_gpios));
359 ret = gpio_request(gpios[i].gpio, gpios[i].name); 353 if (ret)
360 if (ret) { 354 return ret;
361 i--;
362 goto err_gpio;
363 }
364
365 if (gpios[i].output)
366 ret = gpio_direction_output(gpios[i].gpio,
367 gpios[i].value);
368 else
369 ret = gpio_direction_input(gpios[i].gpio);
370
371 if (ret)
372 goto err_gpio;
373 }
374 355
375 mutex_init(&tosa_bat_main.work_lock); 356 mutex_init(&tosa_bat_main.work_lock);
376 mutex_init(&tosa_bat_jacket.work_lock); 357 mutex_init(&tosa_bat_jacket.work_lock);
@@ -424,18 +405,12 @@ err_psy_reg_main:
424 /* see comment in tosa_bat_remove */ 405 /* see comment in tosa_bat_remove */
425 cancel_work_sync(&bat_work); 406 cancel_work_sync(&bat_work);
426 407
427 i--; 408 gpio_free_array(tosa_bat_gpios, ARRAY_SIZE(tosa_bat_gpios));
428err_gpio:
429 for (; i >= 0; i--)
430 gpio_free(gpios[i].gpio);
431
432 return ret; 409 return ret;
433} 410}
434 411
435static int __devexit tosa_bat_remove(struct platform_device *dev) 412static int __devexit tosa_bat_remove(struct platform_device *dev)
436{ 413{
437 int i;
438
439 free_irq(gpio_to_irq(TOSA_GPIO_JACKET_DETECT), &tosa_bat_jacket); 414 free_irq(gpio_to_irq(TOSA_GPIO_JACKET_DETECT), &tosa_bat_jacket);
440 free_irq(gpio_to_irq(TOSA_GPIO_BAT1_CRG), &tosa_bat_jacket); 415 free_irq(gpio_to_irq(TOSA_GPIO_BAT1_CRG), &tosa_bat_jacket);
441 free_irq(gpio_to_irq(TOSA_GPIO_BAT0_CRG), &tosa_bat_main); 416 free_irq(gpio_to_irq(TOSA_GPIO_BAT0_CRG), &tosa_bat_main);
@@ -450,10 +425,7 @@ static int __devexit tosa_bat_remove(struct platform_device *dev)
450 * unregistered now. 425 * unregistered now.
451 */ 426 */
452 cancel_work_sync(&bat_work); 427 cancel_work_sync(&bat_work);
453 428 gpio_free_array(tosa_bat_gpios, ARRAY_SIZE(tosa_bat_gpios));
454 for (i = ARRAY_SIZE(gpios) - 1; i >= 0; i--)
455 gpio_free(gpios[i].gpio);
456
457 return 0; 429 return 0;
458} 430}
459 431
@@ -466,18 +438,7 @@ static struct platform_driver tosa_bat_driver = {
466 .resume = tosa_bat_resume, 438 .resume = tosa_bat_resume,
467}; 439};
468 440
469static int __init tosa_bat_init(void) 441module_platform_driver(tosa_bat_driver);
470{
471 return platform_driver_register(&tosa_bat_driver);
472}
473
474static void __exit tosa_bat_exit(void)
475{
476 platform_driver_unregister(&tosa_bat_driver);
477}
478
479module_init(tosa_bat_init);
480module_exit(tosa_bat_exit);
481 442
482MODULE_LICENSE("GPL"); 443MODULE_LICENSE("GPL");
483MODULE_AUTHOR("Dmitry Baryshkov"); 444MODULE_AUTHOR("Dmitry Baryshkov");
diff --git a/drivers/power/wm831x_backup.c b/drivers/power/wm831x_backup.c
index e648cbea1e6..6243e697512 100644
--- a/drivers/power/wm831x_backup.c
+++ b/drivers/power/wm831x_backup.c
@@ -226,17 +226,7 @@ static struct platform_driver wm831x_backup_driver = {
226 }, 226 },
227}; 227};
228 228
229static int __init wm831x_backup_init(void) 229module_platform_driver(wm831x_backup_driver);
230{
231 return platform_driver_register(&wm831x_backup_driver);
232}
233module_init(wm831x_backup_init);
234
235static void __exit wm831x_backup_exit(void)
236{
237 platform_driver_unregister(&wm831x_backup_driver);
238}
239module_exit(wm831x_backup_exit);
240 230
241MODULE_DESCRIPTION("Backup battery charger driver for WM831x PMICs"); 231MODULE_DESCRIPTION("Backup battery charger driver for WM831x PMICs");
242MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 232MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c
index 6cc2ca6427f..987332b71d8 100644
--- a/drivers/power/wm831x_power.c
+++ b/drivers/power/wm831x_power.c
@@ -27,6 +27,7 @@ struct wm831x_power {
27 char wall_name[20]; 27 char wall_name[20];
28 char usb_name[20]; 28 char usb_name[20];
29 char battery_name[20]; 29 char battery_name[20];
30 bool have_battery;
30}; 31};
31 32
32static int wm831x_power_check_online(struct wm831x *wm831x, int supply, 33static int wm831x_power_check_online(struct wm831x *wm831x, int supply,
@@ -449,7 +450,8 @@ static irqreturn_t wm831x_bat_irq(int irq, void *data)
449 450
450 /* The battery charger is autonomous so we don't need to do 451 /* The battery charger is autonomous so we don't need to do
451 * anything except kick user space */ 452 * anything except kick user space */
452 power_supply_changed(&wm831x_power->battery); 453 if (wm831x_power->have_battery)
454 power_supply_changed(&wm831x_power->battery);
453 455
454 return IRQ_HANDLED; 456 return IRQ_HANDLED;
455} 457}
@@ -479,7 +481,8 @@ static irqreturn_t wm831x_pwr_src_irq(int irq, void *data)
479 dev_dbg(wm831x->dev, "Power source changed\n"); 481 dev_dbg(wm831x->dev, "Power source changed\n");
480 482
481 /* Just notify for everything - little harm in overnotifying. */ 483 /* Just notify for everything - little harm in overnotifying. */
482 power_supply_changed(&wm831x_power->battery); 484 if (wm831x_power->have_battery)
485 power_supply_changed(&wm831x_power->battery);
483 power_supply_changed(&wm831x_power->usb); 486 power_supply_changed(&wm831x_power->usb);
484 power_supply_changed(&wm831x_power->wall); 487 power_supply_changed(&wm831x_power->wall);
485 488
@@ -537,15 +540,6 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev)
537 if (ret) 540 if (ret)
538 goto err_kmalloc; 541 goto err_kmalloc;
539 542
540 battery->name = power->battery_name;
541 battery->properties = wm831x_bat_props;
542 battery->num_properties = ARRAY_SIZE(wm831x_bat_props);
543 battery->get_property = wm831x_bat_get_prop;
544 battery->use_for_apm = 1;
545 ret = power_supply_register(&pdev->dev, battery);
546 if (ret)
547 goto err_wall;
548
549 usb->name = power->usb_name, 543 usb->name = power->usb_name,
550 usb->type = POWER_SUPPLY_TYPE_USB; 544 usb->type = POWER_SUPPLY_TYPE_USB;
551 usb->properties = wm831x_usb_props; 545 usb->properties = wm831x_usb_props;
@@ -553,7 +547,23 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev)
553 usb->get_property = wm831x_usb_get_prop; 547 usb->get_property = wm831x_usb_get_prop;
554 ret = power_supply_register(&pdev->dev, usb); 548 ret = power_supply_register(&pdev->dev, usb);
555 if (ret) 549 if (ret)
556 goto err_battery; 550 goto err_wall;
551
552 ret = wm831x_reg_read(wm831x, WM831X_CHARGER_CONTROL_1);
553 if (ret < 0)
554 goto err_wall;
555 power->have_battery = ret & WM831X_CHG_ENA;
556
557 if (power->have_battery) {
558 battery->name = power->battery_name;
559 battery->properties = wm831x_bat_props;
560 battery->num_properties = ARRAY_SIZE(wm831x_bat_props);
561 battery->get_property = wm831x_bat_get_prop;
562 battery->use_for_apm = 1;
563 ret = power_supply_register(&pdev->dev, battery);
564 if (ret)
565 goto err_usb;
566 }
557 567
558 irq = platform_get_irq_byname(pdev, "SYSLO"); 568 irq = platform_get_irq_byname(pdev, "SYSLO");
559 ret = request_threaded_irq(irq, NULL, wm831x_syslo_irq, 569 ret = request_threaded_irq(irq, NULL, wm831x_syslo_irq,
@@ -562,7 +572,7 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev)
562 if (ret != 0) { 572 if (ret != 0) {
563 dev_err(&pdev->dev, "Failed to request SYSLO IRQ %d: %d\n", 573 dev_err(&pdev->dev, "Failed to request SYSLO IRQ %d: %d\n",
564 irq, ret); 574 irq, ret);
565 goto err_usb; 575 goto err_battery;
566 } 576 }
567 577
568 irq = platform_get_irq_byname(pdev, "PWR SRC"); 578 irq = platform_get_irq_byname(pdev, "PWR SRC");
@@ -601,10 +611,11 @@ err_bat_irq:
601err_syslo: 611err_syslo:
602 irq = platform_get_irq_byname(pdev, "SYSLO"); 612 irq = platform_get_irq_byname(pdev, "SYSLO");
603 free_irq(irq, power); 613 free_irq(irq, power);
614err_battery:
615 if (power->have_battery)
616 power_supply_unregister(battery);
604err_usb: 617err_usb:
605 power_supply_unregister(usb); 618 power_supply_unregister(usb);
606err_battery:
607 power_supply_unregister(battery);
608err_wall: 619err_wall:
609 power_supply_unregister(wall); 620 power_supply_unregister(wall);
610err_kmalloc: 621err_kmalloc:
@@ -628,7 +639,8 @@ static __devexit int wm831x_power_remove(struct platform_device *pdev)
628 irq = platform_get_irq_byname(pdev, "SYSLO"); 639 irq = platform_get_irq_byname(pdev, "SYSLO");
629 free_irq(irq, wm831x_power); 640 free_irq(irq, wm831x_power);
630 641
631 power_supply_unregister(&wm831x_power->battery); 642 if (wm831x_power->have_battery)
643 power_supply_unregister(&wm831x_power->battery);
632 power_supply_unregister(&wm831x_power->wall); 644 power_supply_unregister(&wm831x_power->wall);
633 power_supply_unregister(&wm831x_power->usb); 645 power_supply_unregister(&wm831x_power->usb);
634 kfree(wm831x_power); 646 kfree(wm831x_power);
@@ -643,17 +655,7 @@ static struct platform_driver wm831x_power_driver = {
643 }, 655 },
644}; 656};
645 657
646static int __init wm831x_power_init(void) 658module_platform_driver(wm831x_power_driver);
647{
648 return platform_driver_register(&wm831x_power_driver);
649}
650module_init(wm831x_power_init);
651
652static void __exit wm831x_power_exit(void)
653{
654 platform_driver_unregister(&wm831x_power_driver);
655}
656module_exit(wm831x_power_exit);
657 659
658MODULE_DESCRIPTION("Power supply driver for WM831x PMICs"); 660MODULE_DESCRIPTION("Power supply driver for WM831x PMICs");
659MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 661MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/drivers/power/wm8350_power.c b/drivers/power/wm8350_power.c
index 0693902d615..fae04d38465 100644
--- a/drivers/power/wm8350_power.c
+++ b/drivers/power/wm8350_power.c
@@ -522,17 +522,7 @@ static struct platform_driver wm8350_power_driver = {
522 }, 522 },
523}; 523};
524 524
525static int __init wm8350_power_init(void) 525module_platform_driver(wm8350_power_driver);
526{
527 return platform_driver_register(&wm8350_power_driver);
528}
529module_init(wm8350_power_init);
530
531static void __exit wm8350_power_exit(void)
532{
533 platform_driver_unregister(&wm8350_power_driver);
534}
535module_exit(wm8350_power_exit);
536 526
537MODULE_LICENSE("GPL"); 527MODULE_LICENSE("GPL");
538MODULE_DESCRIPTION("Power supply driver for WM8350"); 528MODULE_DESCRIPTION("Power supply driver for WM8350");
diff --git a/drivers/power/wm97xx_battery.c b/drivers/power/wm97xx_battery.c
index 156559e56fa..d2d4c08c681 100644
--- a/drivers/power/wm97xx_battery.c
+++ b/drivers/power/wm97xx_battery.c
@@ -25,9 +25,8 @@
25#include <linux/irq.h> 25#include <linux/irq.h>
26#include <linux/slab.h> 26#include <linux/slab.h>
27 27
28static DEFINE_MUTEX(bat_lock);
29static struct work_struct bat_work; 28static struct work_struct bat_work;
30static struct mutex work_lock; 29static DEFINE_MUTEX(work_lock);
31static int bat_status = POWER_SUPPLY_STATUS_UNKNOWN; 30static int bat_status = POWER_SUPPLY_STATUS_UNKNOWN;
32static enum power_supply_property *prop; 31static enum power_supply_property *prop;
33 32
@@ -181,8 +180,6 @@ static int __devinit wm97xx_bat_probe(struct platform_device *dev)
181 if (dev->id != -1) 180 if (dev->id != -1)
182 return -EINVAL; 181 return -EINVAL;
183 182
184 mutex_init(&work_lock);
185
186 if (!pdata) { 183 if (!pdata) {
187 dev_err(&dev->dev, "No platform_data supplied\n"); 184 dev_err(&dev->dev, "No platform_data supplied\n");
188 return -EINVAL; 185 return -EINVAL;
@@ -196,7 +193,7 @@ static int __devinit wm97xx_bat_probe(struct platform_device *dev)
196 if (ret) 193 if (ret)
197 goto err2; 194 goto err2;
198 ret = request_irq(gpio_to_irq(pdata->charge_gpio), 195 ret = request_irq(gpio_to_irq(pdata->charge_gpio),
199 wm97xx_chrg_irq, IRQF_DISABLED, 196 wm97xx_chrg_irq, 0,
200 "AC Detect", dev); 197 "AC Detect", dev);
201 if (ret) 198 if (ret)
202 goto err2; 199 goto err2;
@@ -291,18 +288,7 @@ static struct platform_driver wm97xx_bat_driver = {
291 .remove = __devexit_p(wm97xx_bat_remove), 288 .remove = __devexit_p(wm97xx_bat_remove),
292}; 289};
293 290
294static int __init wm97xx_bat_init(void) 291module_platform_driver(wm97xx_bat_driver);
295{
296 return platform_driver_register(&wm97xx_bat_driver);
297}
298
299static void __exit wm97xx_bat_exit(void)
300{
301 platform_driver_unregister(&wm97xx_bat_driver);
302}
303
304module_init(wm97xx_bat_init);
305module_exit(wm97xx_bat_exit);
306 292
307MODULE_LICENSE("GPL"); 293MODULE_LICENSE("GPL");
308MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); 294MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
diff --git a/drivers/power/z2_battery.c b/drivers/power/z2_battery.c
index d119c38b3ff..636ebb2a0e8 100644
--- a/drivers/power/z2_battery.c
+++ b/drivers/power/z2_battery.c
@@ -218,7 +218,7 @@ static int __devinit z2_batt_probe(struct i2c_client *client,
218 irq_set_irq_type(gpio_to_irq(info->charge_gpio), 218 irq_set_irq_type(gpio_to_irq(info->charge_gpio),
219 IRQ_TYPE_EDGE_BOTH); 219 IRQ_TYPE_EDGE_BOTH);
220 ret = request_irq(gpio_to_irq(info->charge_gpio), 220 ret = request_irq(gpio_to_irq(info->charge_gpio),
221 z2_charge_switch_irq, IRQF_DISABLED, 221 z2_charge_switch_irq, 0,
222 "AC Detect", charger); 222 "AC Detect", charger);
223 if (ret) 223 if (ret)
224 goto err3; 224 goto err3;
@@ -313,7 +313,7 @@ static struct i2c_driver z2_batt_driver = {
313 .pm = Z2_BATTERY_PM_OPS 313 .pm = Z2_BATTERY_PM_OPS
314 }, 314 },
315 .probe = z2_batt_probe, 315 .probe = z2_batt_probe,
316 .remove = z2_batt_remove, 316 .remove = __devexit_p(z2_batt_remove),
317 .id_table = z2_batt_id, 317 .id_table = z2_batt_id,
318}; 318};
319 319
diff --git a/include/linux/lp8727.h b/include/linux/lp8727.h
new file mode 100755
index 00000000000..d21fa2865bf
--- /dev/null
+++ b/include/linux/lp8727.h
@@ -0,0 +1,51 @@
1/*
2 * Copyright (C) 2011 National Semiconductor
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef _LP8727_H
10#define _LP8727_H
11
12enum lp8727_eoc_level {
13 EOC_5P,
14 EOC_10P,
15 EOC_16P,
16 EOC_20P,
17 EOC_25P,
18 EOC_33P,
19 EOC_50P,
20};
21
22enum lp8727_ichg {
23 ICHG_90mA,
24 ICHG_100mA,
25 ICHG_400mA,
26 ICHG_450mA,
27 ICHG_500mA,
28 ICHG_600mA,
29 ICHG_700mA,
30 ICHG_800mA,
31 ICHG_900mA,
32 ICHG_1000mA,
33};
34
35struct lp8727_chg_param {
36 /* end of charge level setting */
37 enum lp8727_eoc_level eoc_level;
38 /* charging current */
39 enum lp8727_ichg ichg;
40};
41
42struct lp8727_platform_data {
43 u8 (*get_batt_present)(void);
44 u16 (*get_batt_level)(void);
45 u8 (*get_batt_capacity)(void);
46 u8 (*get_batt_temp)(void);
47 struct lp8727_chg_param ac;
48 struct lp8727_chg_param usb;
49};
50
51#endif
diff --git a/include/linux/mfd/max8925.h b/include/linux/mfd/max8925.h
index 5259dfe8c58..b8e6d944908 100644
--- a/include/linux/mfd/max8925.h
+++ b/include/linux/mfd/max8925.h
@@ -167,9 +167,6 @@ enum {
167 MAX8925_IRQ_VCHG_DC_OVP, 167 MAX8925_IRQ_VCHG_DC_OVP,
168 MAX8925_IRQ_VCHG_DC_F, 168 MAX8925_IRQ_VCHG_DC_F,
169 MAX8925_IRQ_VCHG_DC_R, 169 MAX8925_IRQ_VCHG_DC_R,
170 MAX8925_IRQ_VCHG_USB_OVP,
171 MAX8925_IRQ_VCHG_USB_F,
172 MAX8925_IRQ_VCHG_USB_R,
173 MAX8925_IRQ_VCHG_THM_OK_R, 170 MAX8925_IRQ_VCHG_THM_OK_R,
174 MAX8925_IRQ_VCHG_THM_OK_F, 171 MAX8925_IRQ_VCHG_THM_OK_F,
175 MAX8925_IRQ_VCHG_SYSLOW_F, 172 MAX8925_IRQ_VCHG_SYSLOW_F,
@@ -223,6 +220,10 @@ struct max8925_power_pdata {
223 unsigned batt_detect:1; 220 unsigned batt_detect:1;
224 unsigned topoff_threshold:2; 221 unsigned topoff_threshold:2;
225 unsigned fast_charge:3; /* charge current */ 222 unsigned fast_charge:3; /* charge current */
223 unsigned no_temp_support:1; /* set if no temperature detect */
224 unsigned no_insert_detect:1; /* set if no ac insert detect */
225 char **supplied_to;
226 int num_supplicants;
226}; 227};
227 228
228/* 229/*
diff --git a/include/linux/pda_power.h b/include/linux/pda_power.h
index c9e4d814ff7..2bb62bf296a 100644
--- a/include/linux/pda_power.h
+++ b/include/linux/pda_power.h
@@ -35,6 +35,8 @@ struct pda_power_pdata {
35 unsigned int polling_interval; /* msecs, default is 2000 */ 35 unsigned int polling_interval; /* msecs, default is 2000 */
36 36
37 unsigned long ac_max_uA; /* current to draw when on AC */ 37 unsigned long ac_max_uA; /* current to draw when on AC */
38
39 bool use_otg_notifier;
38}; 40};
39 41
40#endif /* __PDA_POWER_H__ */ 42#endif /* __PDA_POWER_H__ */
diff --git a/include/linux/power/charger-manager.h b/include/linux/power/charger-manager.h
new file mode 100644
index 00000000000..4f75e531c11
--- /dev/null
+++ b/include/linux/power/charger-manager.h
@@ -0,0 +1,147 @@
1/*
2 * Copyright (C) 2011 Samsung Electronics Co., Ltd.
3 * MyungJoo.Ham <myungjoo.ham@samsung.com>
4 *
5 * Charger Manager.
6 * This framework enables to control and multiple chargers and to
7 * monitor charging even in the context of suspend-to-RAM with
8 * an interface combining the chargers.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13**/
14
15#ifndef _CHARGER_MANAGER_H
16#define _CHARGER_MANAGER_H
17
18#include <linux/power_supply.h>
19
20enum data_source {
21 CM_FUEL_GAUGE,
22 CM_CHARGER_STAT,
23};
24
25enum polling_modes {
26 CM_POLL_DISABLE = 0,
27 CM_POLL_ALWAYS,
28 CM_POLL_EXTERNAL_POWER_ONLY,
29 CM_POLL_CHARGING_ONLY,
30};
31
32/**
33 * struct charger_global_desc
34 * @rtc_name: the name of RTC used to wake up the system from suspend.
35 * @rtc_only_wakeup:
36 * If the system is woken up by waekup-sources other than the RTC or
37 * callbacks, Charger Manager should recognize with
38 * rtc_only_wakeup() returning false.
39 * If the RTC given to CM is the only wakeup reason,
40 * rtc_only_wakeup should return true.
41 */
42struct charger_global_desc {
43 char *rtc_name;
44
45 bool (*rtc_only_wakeup)(void);
46};
47
48/**
49 * struct charger_desc
50 * @psy_name: the name of power-supply-class for charger manager
51 * @polling_mode:
52 * Determine which polling mode will be used
53 * @fullbatt_uV: voltage in microvolt
54 * If it is not being charged and VBATT >= fullbatt_uV,
55 * it is assumed to be full.
56 * @polling_interval_ms: interval in millisecond at which
57 * charger manager will monitor battery health
58 * @battery_present:
59 * Specify where information for existance of battery can be obtained
60 * @psy_charger_stat: the names of power-supply for chargers
61 * @num_charger_regulator: the number of entries in charger_regulators
62 * @charger_regulators: array of regulator_bulk_data for chargers
63 * @psy_fuel_gauge: the name of power-supply for fuel gauge
64 * @temperature_out_of_range:
65 * Determine whether the status is overheat or cold or normal.
66 * return_value > 0: overheat
67 * return_value == 0: normal
68 * return_value < 0: cold
69 * @measure_battery_temp:
70 * true: measure battery temperature
71 * false: measure ambient temperature
72 */
73struct charger_desc {
74 char *psy_name;
75
76 enum polling_modes polling_mode;
77 unsigned int polling_interval_ms;
78
79 unsigned int fullbatt_uV;
80
81 enum data_source battery_present;
82
83 char **psy_charger_stat;
84
85 int num_charger_regulators;
86 struct regulator_bulk_data *charger_regulators;
87
88 char *psy_fuel_gauge;
89
90 int (*temperature_out_of_range)(int *mC);
91 bool measure_battery_temp;
92};
93
94#define PSY_NAME_MAX 30
95
96/**
97 * struct charger_manager
98 * @entry: entry for list
99 * @dev: device pointer
100 * @desc: instance of charger_desc
101 * @fuel_gauge: power_supply for fuel gauge
102 * @charger_stat: array of power_supply for chargers
103 * @charger_enabled: the state of charger
104 * @emergency_stop:
105 * When setting true, stop charging
106 * @last_temp_mC: the measured temperature in milli-Celsius
107 * @psy_name_buf: the name of power-supply-class for charger manager
108 * @charger_psy: power_supply for charger manager
109 * @status_save_ext_pwr_inserted:
110 * saved status of external power before entering suspend-to-RAM
111 * @status_save_batt:
112 * saved status of battery before entering suspend-to-RAM
113 */
114struct charger_manager {
115 struct list_head entry;
116 struct device *dev;
117 struct charger_desc *desc;
118
119 struct power_supply *fuel_gauge;
120 struct power_supply **charger_stat;
121
122 bool charger_enabled;
123
124 int emergency_stop;
125 int last_temp_mC;
126
127 char psy_name_buf[PSY_NAME_MAX + 1];
128 struct power_supply charger_psy;
129
130 bool status_save_ext_pwr_inserted;
131 bool status_save_batt;
132};
133
134#ifdef CONFIG_CHARGER_MANAGER
135extern int setup_charger_manager(struct charger_global_desc *gd);
136extern bool cm_suspend_again(void);
137#else
138static void __maybe_unused setup_charger_manager(struct charger_global_desc *gd)
139{ }
140
141static bool __maybe_unused cm_suspend_again(void)
142{
143 return false;
144}
145#endif
146
147#endif /* _CHARGER_MANAGER_H */
diff --git a/include/linux/power/bq20z75.h b/include/linux/power/sbs-battery.h
index 1398eb004e8..2b0a9d9ff57 100644
--- a/include/linux/power/bq20z75.h
+++ b/include/linux/power/sbs-battery.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Gas Gauge driver for TI's BQ20Z75 2 * Gas Gauge driver for SBS Compliant Gas Gauges
3 * 3 *
4 * Copyright (c) 2010, NVIDIA Corporation. 4 * Copyright (c) 2010, NVIDIA Corporation.
5 * 5 *
@@ -18,21 +18,21 @@
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */ 19 */
20 20
21#ifndef __LINUX_POWER_BQ20Z75_H_ 21#ifndef __LINUX_POWER_SBS_BATTERY_H_
22#define __LINUX_POWER_BQ20Z75_H_ 22#define __LINUX_POWER_SBS_BATTERY_H_
23 23
24#include <linux/power_supply.h> 24#include <linux/power_supply.h>
25#include <linux/types.h> 25#include <linux/types.h>
26 26
27/** 27/**
28 * struct bq20z75_platform_data - platform data for bq20z75 devices 28 * struct sbs_platform_data - platform data for sbs devices
29 * @battery_detect: GPIO which is used to detect battery presence 29 * @battery_detect: GPIO which is used to detect battery presence
30 * @battery_detect_present: gpio state when battery is present (0 / 1) 30 * @battery_detect_present: gpio state when battery is present (0 / 1)
31 * @i2c_retry_count: # of times to retry on i2c IO failure 31 * @i2c_retry_count: # of times to retry on i2c IO failure
32 * @poll_retry_count: # of times to retry looking for new status after 32 * @poll_retry_count: # of times to retry looking for new status after
33 * external change notification 33 * external change notification
34 */ 34 */
35struct bq20z75_platform_data { 35struct sbs_platform_data {
36 int battery_detect; 36 int battery_detect;
37 int battery_detect_present; 37 int battery_detect_present;
38 int i2c_retry_count; 38 int i2c_retry_count;
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 204c18dfdc9..fa9b962aec1 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -74,6 +74,12 @@ enum {
74 POWER_SUPPLY_CAPACITY_LEVEL_FULL, 74 POWER_SUPPLY_CAPACITY_LEVEL_FULL,
75}; 75};
76 76
77enum {
78 POWER_SUPPLY_SCOPE_UNKNOWN = 0,
79 POWER_SUPPLY_SCOPE_SYSTEM,
80 POWER_SUPPLY_SCOPE_DEVICE,
81};
82
77enum power_supply_property { 83enum power_supply_property {
78 /* Properties of type `int' */ 84 /* Properties of type `int' */
79 POWER_SUPPLY_PROP_STATUS = 0, 85 POWER_SUPPLY_PROP_STATUS = 0,
@@ -116,6 +122,7 @@ enum power_supply_property {
116 POWER_SUPPLY_PROP_TIME_TO_FULL_NOW, 122 POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
117 POWER_SUPPLY_PROP_TIME_TO_FULL_AVG, 123 POWER_SUPPLY_PROP_TIME_TO_FULL_AVG,
118 POWER_SUPPLY_PROP_TYPE, /* use power_supply.type instead */ 124 POWER_SUPPLY_PROP_TYPE, /* use power_supply.type instead */
125 POWER_SUPPLY_PROP_SCOPE,
119 /* Properties of type `const char *' */ 126 /* Properties of type `const char *' */
120 POWER_SUPPLY_PROP_MODEL_NAME, 127 POWER_SUPPLY_PROP_MODEL_NAME,
121 POWER_SUPPLY_PROP_MANUFACTURER, 128 POWER_SUPPLY_PROP_MANUFACTURER,
@@ -123,7 +130,8 @@ enum power_supply_property {
123}; 130};
124 131
125enum power_supply_type { 132enum power_supply_type {
126 POWER_SUPPLY_TYPE_BATTERY = 0, 133 POWER_SUPPLY_TYPE_UNKNOWN = 0,
134 POWER_SUPPLY_TYPE_BATTERY,
127 POWER_SUPPLY_TYPE_UPS, 135 POWER_SUPPLY_TYPE_UPS,
128 POWER_SUPPLY_TYPE_MAINS, 136 POWER_SUPPLY_TYPE_MAINS,
129 POWER_SUPPLY_TYPE_USB, /* Standard Downstream Port */ 137 POWER_SUPPLY_TYPE_USB, /* Standard Downstream Port */
@@ -211,6 +219,7 @@ static inline int power_supply_is_system_supplied(void) { return -ENOSYS; }
211extern int power_supply_register(struct device *parent, 219extern int power_supply_register(struct device *parent,
212 struct power_supply *psy); 220 struct power_supply *psy);
213extern void power_supply_unregister(struct power_supply *psy); 221extern void power_supply_unregister(struct power_supply *psy);
222extern int power_supply_powers(struct power_supply *psy, struct device *dev);
214 223
215/* For APM emulation, think legacy userspace. */ 224/* For APM emulation, think legacy userspace. */
216extern struct class *power_supply_class; 225extern struct class *power_supply_class;
diff --git a/include/linux/s3c_adc_battery.h b/include/linux/s3c_adc_battery.h
index fbe58b7e63e..99dadbffdd4 100644
--- a/include/linux/s3c_adc_battery.h
+++ b/include/linux/s3c_adc_battery.h
@@ -25,6 +25,10 @@ struct s3c_adc_bat_pdata {
25 const unsigned int current_channel; 25 const unsigned int current_channel;
26 const unsigned int backup_volt_channel; 26 const unsigned int backup_volt_channel;
27 27
28 const unsigned int volt_samples;
29 const unsigned int current_samples;
30 const unsigned int backup_volt_samples;
31
28 const unsigned int volt_mult; 32 const unsigned int volt_mult;
29 const unsigned int current_mult; 33 const unsigned int current_mult;
30 const unsigned int backup_volt_mult; 34 const unsigned int backup_volt_mult;