aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-08-06 23:05:34 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-08-06 23:05:34 -0400
commit0498cf8429011ec968870b3fee7570a751575a35 (patch)
tree1e0cd91db7a780c323fb97b0fbae8a9da51cae03
parent85417aef44fc58b08773117ceb1bc6ca5684e973 (diff)
parent5e37195f30cc31e6a1052cbc282254e127c1b8c7 (diff)
Merge tag 'for-v3.17' of git://git.infradead.org/battery-2.6
Pull power supply changes from Sebastian Reichel: - Added iPaq h3xxx battery driver - Added Broadcom STB reset driver - DT support for rx51-battery - misc. fixes * tag 'for-v3.17' of git://git.infradead.org/battery-2.6: ipaq_micro_battery: fix sparse non static symbol warning power: add driver for battery reading on iPaq h3xxx power: twl4030_charger: detect battery presence prior to enabling charger power: reset: Add reboot driver for brcmstb power_supply: Fix sparse non static symbol warning power_supply: Add inlmt,iterm, min/max temp props charger: tps65090: Allow charger module to be used when no irq power/reset: Fix GPL v2 license string typo power: poweroff: gpio: convert to use descriptors bq27000: report missing device better. bq27x00_battery: Introduce the use of the managed version of kzalloc Documentation: DT: Document rx51-battery binding rx51_battery: convert to iio consumer bq2415x_charger: Fix Atomic Sleep Bug
-rw-r--r--Documentation/devicetree/bindings/power/rx51-battery.txt25
-rw-r--r--Documentation/power/power_supply_class.txt6
-rw-r--r--drivers/power/Kconfig7
-rw-r--r--drivers/power/Makefile1
-rw-r--r--drivers/power/bq2415x_charger.c8
-rw-r--r--drivers/power/bq27x00_battery.c28
-rw-r--r--drivers/power/ipaq_micro_battery.c290
-rw-r--r--drivers/power/power_supply_core.c3
-rw-r--r--drivers/power/power_supply_sysfs.c4
-rw-r--r--drivers/power/reset/Kconfig11
-rw-r--r--drivers/power/reset/Makefile1
-rw-r--r--drivers/power/reset/brcmstb-reboot.c120
-rw-r--r--drivers/power/reset/gpio-poweroff.c52
-rw-r--r--drivers/power/reset/restart-poweroff.c2
-rw-r--r--drivers/power/rx51_battery.c90
-rw-r--r--drivers/power/tps65090-charger.c76
-rw-r--r--drivers/power/twl4030_charger.c44
-rw-r--r--include/linux/power_supply.h4
18 files changed, 673 insertions, 99 deletions
diff --git a/Documentation/devicetree/bindings/power/rx51-battery.txt b/Documentation/devicetree/bindings/power/rx51-battery.txt
new file mode 100644
index 000000000000..90438453db58
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/rx51-battery.txt
@@ -0,0 +1,25 @@
1Binding for Nokia N900 battery
2
3The Nokia N900 battery status can be read via the TWL4030's A/D converter.
4
5Required properties:
6- compatible: Should contain one of the following:
7 * "nokia,n900-battery"
8- io-channels: Should contain IIO channel specifiers
9 for each element in io-channel-names.
10- io-channel-names: Should contain the following values:
11 * "temp" - The ADC channel for temperature reading
12 * "bsi" - The ADC channel for battery size identification
13 * "vbat" - The ADC channel to measure the battery voltage
14
15Example from Nokia N900:
16
17battery: n900-battery {
18 compatible = "nokia,n900-battery";
19 io-channels = <&twl4030_madc 0>,
20 <&twl4030_madc 4>,
21 <&twl4030_madc 12>;
22 io-channel-names = "temp",
23 "bsi",
24 "vbat";
25};
diff --git a/Documentation/power/power_supply_class.txt b/Documentation/power/power_supply_class.txt
index 89a8816990ff..48cff881cb8a 100644
--- a/Documentation/power/power_supply_class.txt
+++ b/Documentation/power/power_supply_class.txt
@@ -118,6 +118,10 @@ relative, time-based measurements.
118CONSTANT_CHARGE_CURRENT - constant charge current programmed by charger. 118CONSTANT_CHARGE_CURRENT - constant charge current programmed by charger.
119CONSTANT_CHARGE_CURRENT_MAX - maximum charge current supported by the 119CONSTANT_CHARGE_CURRENT_MAX - maximum charge current supported by the
120power supply object. 120power supply object.
121INPUT_CURRENT_LIMIT - input current limit programmed by charger. Indicates
122the current drawn from a charging source.
123CHARGE_TERM_CURRENT - Charge termination current used to detect the end of charge
124condition.
121 125
122CONSTANT_CHARGE_VOLTAGE - constant charge voltage programmed by charger. 126CONSTANT_CHARGE_VOLTAGE - constant charge voltage programmed by charger.
123CONSTANT_CHARGE_VOLTAGE_MAX - maximum charge voltage supported by the 127CONSTANT_CHARGE_VOLTAGE_MAX - maximum charge voltage supported by the
@@ -140,6 +144,8 @@ TEMP_ALERT_MAX - maximum battery temperature alert.
140TEMP_AMBIENT - ambient temperature. 144TEMP_AMBIENT - ambient temperature.
141TEMP_AMBIENT_ALERT_MIN - minimum ambient temperature alert. 145TEMP_AMBIENT_ALERT_MIN - minimum ambient temperature alert.
142TEMP_AMBIENT_ALERT_MAX - maximum ambient temperature alert. 146TEMP_AMBIENT_ALERT_MAX - maximum ambient temperature alert.
147TEMP_MIN - minimum operatable temperature
148TEMP_MAX - maximum operatable temperature
143 149
144TIME_TO_EMPTY - seconds left for battery to be considered empty (i.e. 150TIME_TO_EMPTY - seconds left for battery to be considered empty (i.e.
145while battery powers a load) 151while battery powers a load)
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index ba6975123071..73cfcdf28a36 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -137,6 +137,13 @@ config BATTERY_COLLIE
137 Say Y to enable support for the battery on the Sharp Zaurus 137 Say Y to enable support for the battery on the Sharp Zaurus
138 SL-5500 (collie) models. 138 SL-5500 (collie) models.
139 139
140config BATTERY_IPAQ_MICRO
141 tristate "iPAQ Atmel Micro ASIC battery driver"
142 depends on MFD_IPAQ_MICRO
143 help
144 Choose this option if you want to monitor battery status on
145 Compaq/HP iPAQ h3100 and h3600.
146
140config BATTERY_WM97XX 147config BATTERY_WM97XX
141 bool "WM97xx generic battery driver" 148 bool "WM97xx generic battery driver"
142 depends on TOUCHSCREEN_WM97XX=y 149 depends on TOUCHSCREEN_WM97XX=y
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index ee54a3e4c90a..dfa894273926 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o
25obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o 25obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o
26obj-$(CONFIG_BATTERY_TOSA) += tosa_battery.o 26obj-$(CONFIG_BATTERY_TOSA) += tosa_battery.o
27obj-$(CONFIG_BATTERY_COLLIE) += collie_battery.o 27obj-$(CONFIG_BATTERY_COLLIE) += collie_battery.o
28obj-$(CONFIG_BATTERY_IPAQ_MICRO) += ipaq_micro_battery.o
28obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o 29obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o
29obj-$(CONFIG_BATTERY_SBS) += sbs-battery.o 30obj-$(CONFIG_BATTERY_SBS) += sbs-battery.o
30obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o 31obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o
diff --git a/drivers/power/bq2415x_charger.c b/drivers/power/bq2415x_charger.c
index 79a37f6d3307..e384844a1ae1 100644
--- a/drivers/power/bq2415x_charger.c
+++ b/drivers/power/bq2415x_charger.c
@@ -840,8 +840,7 @@ static int bq2415x_notifier_call(struct notifier_block *nb,
840 if (bq->automode < 1) 840 if (bq->automode < 1)
841 return NOTIFY_OK; 841 return NOTIFY_OK;
842 842
843 sysfs_notify(&bq->charger.dev->kobj, NULL, "reported_mode"); 843 schedule_delayed_work(&bq->work, 0);
844 bq2415x_set_mode(bq, bq->reported_mode);
845 844
846 return NOTIFY_OK; 845 return NOTIFY_OK;
847} 846}
@@ -892,6 +891,11 @@ static void bq2415x_timer_work(struct work_struct *work)
892 int error; 891 int error;
893 int boost; 892 int boost;
894 893
894 if (bq->automode > 0 && (bq->reported_mode != bq->mode)) {
895 sysfs_notify(&bq->charger.dev->kobj, NULL, "reported_mode");
896 bq2415x_set_mode(bq, bq->reported_mode);
897 }
898
895 if (!bq->autotimer) 899 if (!bq->autotimer)
896 return; 900 return;
897 901
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c
index b309713b63bc..e10763e3a1d5 100644
--- a/drivers/power/bq27x00_battery.c
+++ b/drivers/power/bq27x00_battery.c
@@ -25,6 +25,7 @@
25 * http://www.ti.com/product/bq27425-g1 25 * http://www.ti.com/product/bq27425-g1
26 */ 26 */
27 27
28#include <linux/device.h>
28#include <linux/module.h> 29#include <linux/module.h>
29#include <linux/param.h> 30#include <linux/param.h>
30#include <linux/jiffies.h> 31#include <linux/jiffies.h>
@@ -415,6 +416,9 @@ static void bq27x00_update(struct bq27x00_device_info *di)
415 bool is_bq27425 = di->chip == BQ27425; 416 bool is_bq27425 = di->chip == BQ27425;
416 417
417 cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, !is_bq27500); 418 cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, !is_bq27500);
419 if ((cache.flags & 0xff) == 0xff)
420 /* read error */
421 cache.flags = -1;
418 if (cache.flags >= 0) { 422 if (cache.flags >= 0) {
419 if (!is_bq27500 && !is_bq27425 423 if (!is_bq27500 && !is_bq27425
420 && (cache.flags & BQ27000_FLAG_CI)) { 424 && (cache.flags & BQ27000_FLAG_CI)) {
@@ -804,7 +808,7 @@ static int bq27x00_battery_probe(struct i2c_client *client,
804 goto batt_failed_1; 808 goto batt_failed_1;
805 } 809 }
806 810
807 di = kzalloc(sizeof(*di), GFP_KERNEL); 811 di = devm_kzalloc(&client->dev, sizeof(*di), GFP_KERNEL);
808 if (!di) { 812 if (!di) {
809 dev_err(&client->dev, "failed to allocate device info data\n"); 813 dev_err(&client->dev, "failed to allocate device info data\n");
810 retval = -ENOMEM; 814 retval = -ENOMEM;
@@ -819,14 +823,12 @@ static int bq27x00_battery_probe(struct i2c_client *client,
819 823
820 retval = bq27x00_powersupply_init(di); 824 retval = bq27x00_powersupply_init(di);
821 if (retval) 825 if (retval)
822 goto batt_failed_3; 826 goto batt_failed_2;
823 827
824 i2c_set_clientdata(client, di); 828 i2c_set_clientdata(client, di);
825 829
826 return 0; 830 return 0;
827 831
828batt_failed_3:
829 kfree(di);
830batt_failed_2: 832batt_failed_2:
831 kfree(name); 833 kfree(name);
832batt_failed_1: 834batt_failed_1:
@@ -849,8 +851,6 @@ static int bq27x00_battery_remove(struct i2c_client *client)
849 idr_remove(&battery_id, di->id); 851 idr_remove(&battery_id, di->id);
850 mutex_unlock(&battery_mutex); 852 mutex_unlock(&battery_mutex);
851 853
852 kfree(di);
853
854 return 0; 854 return 0;
855} 855}
856 856
@@ -933,7 +933,6 @@ static int bq27000_battery_probe(struct platform_device *pdev)
933{ 933{
934 struct bq27x00_device_info *di; 934 struct bq27x00_device_info *di;
935 struct bq27000_platform_data *pdata = pdev->dev.platform_data; 935 struct bq27000_platform_data *pdata = pdev->dev.platform_data;
936 int ret;
937 936
938 if (!pdata) { 937 if (!pdata) {
939 dev_err(&pdev->dev, "no platform_data supplied\n"); 938 dev_err(&pdev->dev, "no platform_data supplied\n");
@@ -945,7 +944,7 @@ static int bq27000_battery_probe(struct platform_device *pdev)
945 return -EINVAL; 944 return -EINVAL;
946 } 945 }
947 946
948 di = kzalloc(sizeof(*di), GFP_KERNEL); 947 di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
949 if (!di) { 948 if (!di) {
950 dev_err(&pdev->dev, "failed to allocate device info data\n"); 949 dev_err(&pdev->dev, "failed to allocate device info data\n");
951 return -ENOMEM; 950 return -ENOMEM;
@@ -959,16 +958,7 @@ static int bq27000_battery_probe(struct platform_device *pdev)
959 di->bat.name = pdata->name ?: dev_name(&pdev->dev); 958 di->bat.name = pdata->name ?: dev_name(&pdev->dev);
960 di->bus.read = &bq27000_read_platform; 959 di->bus.read = &bq27000_read_platform;
961 960
962 ret = bq27x00_powersupply_init(di); 961 return bq27x00_powersupply_init(di);
963 if (ret)
964 goto err_free;
965
966 return 0;
967
968err_free:
969 kfree(di);
970
971 return ret;
972} 962}
973 963
974static int bq27000_battery_remove(struct platform_device *pdev) 964static int bq27000_battery_remove(struct platform_device *pdev)
@@ -977,8 +967,6 @@ static int bq27000_battery_remove(struct platform_device *pdev)
977 967
978 bq27x00_powersupply_unregister(di); 968 bq27x00_powersupply_unregister(di);
979 969
980 kfree(di);
981
982 return 0; 970 return 0;
983} 971}
984 972
diff --git a/drivers/power/ipaq_micro_battery.c b/drivers/power/ipaq_micro_battery.c
new file mode 100644
index 000000000000..9d694605cdb7
--- /dev/null
+++ b/drivers/power/ipaq_micro_battery.c
@@ -0,0 +1,290 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License version 2 as
4 * published by the Free Software Foundation.
5 *
6 * h3xxx atmel micro companion support, battery subdevice
7 * based on previous kernel 2.4 version
8 * Author : Alessandro Gardich <gremlin@gremlin.it>
9 * Author : Linus Walleij <linus.walleij@linaro.org>
10 *
11 */
12
13#include <linux/module.h>
14#include <linux/init.h>
15#include <linux/platform_device.h>
16#include <linux/mfd/ipaq-micro.h>
17#include <linux/power_supply.h>
18#include <linux/workqueue.h>
19
20#define BATT_PERIOD 100000 /* 100 seconds in milliseconds */
21
22#define MICRO_BATT_CHEM_ALKALINE 0x01
23#define MICRO_BATT_CHEM_NICD 0x02
24#define MICRO_BATT_CHEM_NIMH 0x03
25#define MICRO_BATT_CHEM_LION 0x04
26#define MICRO_BATT_CHEM_LIPOLY 0x05
27#define MICRO_BATT_CHEM_NOT_INSTALLED 0x06
28#define MICRO_BATT_CHEM_UNKNOWN 0xff
29
30#define MICRO_BATT_STATUS_HIGH 0x01
31#define MICRO_BATT_STATUS_LOW 0x02
32#define MICRO_BATT_STATUS_CRITICAL 0x04
33#define MICRO_BATT_STATUS_CHARGING 0x08
34#define MICRO_BATT_STATUS_CHARGEMAIN 0x10
35#define MICRO_BATT_STATUS_DEAD 0x20 /* Battery will not charge */
36#define MICRO_BATT_STATUS_NOTINSTALLED 0x20 /* For expansion pack batteries */
37#define MICRO_BATT_STATUS_FULL 0x40 /* Battery fully charged */
38#define MICRO_BATT_STATUS_NOBATTERY 0x80
39#define MICRO_BATT_STATUS_UNKNOWN 0xff
40
41struct micro_battery {
42 struct ipaq_micro *micro;
43 struct workqueue_struct *wq;
44 struct delayed_work update;
45 u8 ac;
46 u8 chemistry;
47 unsigned int voltage;
48 u16 temperature;
49 u8 flag;
50};
51
52static void micro_battery_work(struct work_struct *work)
53{
54 struct micro_battery *mb = container_of(work,
55 struct micro_battery, update.work);
56 struct ipaq_micro_msg msg_battery = {
57 .id = MSG_BATTERY,
58 };
59 struct ipaq_micro_msg msg_sensor = {
60 .id = MSG_THERMAL_SENSOR,
61 };
62
63 /* First send battery message */
64 ipaq_micro_tx_msg_sync(mb->micro, &msg_battery);
65 if (msg_battery.rx_len < 4)
66 pr_info("ERROR");
67
68 /*
69 * Returned message format:
70 * byte 0: 0x00 = Not plugged in
71 * 0x01 = AC adapter plugged in
72 * byte 1: chemistry
73 * byte 2: voltage LSB
74 * byte 3: voltage MSB
75 * byte 4: flags
76 * byte 5-9: same for battery 2
77 */
78 mb->ac = msg_battery.rx_data[0];
79 mb->chemistry = msg_battery.rx_data[1];
80 mb->voltage = ((((unsigned short)msg_battery.rx_data[3] << 8) +
81 msg_battery.rx_data[2]) * 5000L) * 1000 / 1024;
82 mb->flag = msg_battery.rx_data[4];
83
84 if (msg_battery.rx_len == 9)
85 pr_debug("second battery ignored\n");
86
87 /* Then read the sensor */
88 ipaq_micro_tx_msg_sync(mb->micro, &msg_sensor);
89 mb->temperature = msg_sensor.rx_data[1] << 8 | msg_sensor.rx_data[0];
90
91 queue_delayed_work(mb->wq, &mb->update, msecs_to_jiffies(BATT_PERIOD));
92}
93
94static int get_capacity(struct power_supply *b)
95{
96 struct micro_battery *mb = dev_get_drvdata(b->dev->parent);
97
98 switch (mb->flag & 0x07) {
99 case MICRO_BATT_STATUS_HIGH:
100 return 100;
101 break;
102 case MICRO_BATT_STATUS_LOW:
103 return 50;
104 break;
105 case MICRO_BATT_STATUS_CRITICAL:
106 return 5;
107 break;
108 default:
109 break;
110 }
111 return 0;
112}
113
114static int get_status(struct power_supply *b)
115{
116 struct micro_battery *mb = dev_get_drvdata(b->dev->parent);
117
118 if (mb->flag == MICRO_BATT_STATUS_UNKNOWN)
119 return POWER_SUPPLY_STATUS_UNKNOWN;
120
121 if (mb->flag & MICRO_BATT_STATUS_FULL)
122 return POWER_SUPPLY_STATUS_FULL;
123
124 if ((mb->flag & MICRO_BATT_STATUS_CHARGING) ||
125 (mb->flag & MICRO_BATT_STATUS_CHARGEMAIN))
126 return POWER_SUPPLY_STATUS_CHARGING;
127
128 return POWER_SUPPLY_STATUS_DISCHARGING;
129}
130
131static int micro_batt_get_property(struct power_supply *b,
132 enum power_supply_property psp,
133 union power_supply_propval *val)
134{
135 struct micro_battery *mb = dev_get_drvdata(b->dev->parent);
136
137 switch (psp) {
138 case POWER_SUPPLY_PROP_TECHNOLOGY:
139 switch (mb->chemistry) {
140 case MICRO_BATT_CHEM_NICD:
141 val->intval = POWER_SUPPLY_TECHNOLOGY_NiCd;
142 break;
143 case MICRO_BATT_CHEM_NIMH:
144 val->intval = POWER_SUPPLY_TECHNOLOGY_NiMH;
145 break;
146 case MICRO_BATT_CHEM_LION:
147 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
148 break;
149 case MICRO_BATT_CHEM_LIPOLY:
150 val->intval = POWER_SUPPLY_TECHNOLOGY_LIPO;
151 break;
152 default:
153 val->intval = POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
154 break;
155 };
156 break;
157 case POWER_SUPPLY_PROP_STATUS:
158 val->intval = get_status(b);
159 break;
160 case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
161 val->intval = 4700000;
162 break;
163 case POWER_SUPPLY_PROP_CAPACITY:
164 val->intval = get_capacity(b);
165 break;
166 case POWER_SUPPLY_PROP_TEMP:
167 val->intval = mb->temperature;
168 break;
169 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
170 val->intval = mb->voltage;
171 break;
172 default:
173 return -EINVAL;
174 };
175
176 return 0;
177}
178
179static int micro_ac_get_property(struct power_supply *b,
180 enum power_supply_property psp,
181 union power_supply_propval *val)
182{
183 struct micro_battery *mb = dev_get_drvdata(b->dev->parent);
184
185 switch (psp) {
186 case POWER_SUPPLY_PROP_ONLINE:
187 val->intval = mb->ac;
188 break;
189 default:
190 return -EINVAL;
191 };
192
193 return 0;
194}
195
196static enum power_supply_property micro_batt_power_props[] = {
197 POWER_SUPPLY_PROP_TECHNOLOGY,
198 POWER_SUPPLY_PROP_STATUS,
199 POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
200 POWER_SUPPLY_PROP_CAPACITY,
201 POWER_SUPPLY_PROP_TEMP,
202 POWER_SUPPLY_PROP_VOLTAGE_NOW,
203};
204
205static struct power_supply micro_batt_power = {
206 .name = "main-battery",
207 .type = POWER_SUPPLY_TYPE_BATTERY,
208 .properties = micro_batt_power_props,
209 .num_properties = ARRAY_SIZE(micro_batt_power_props),
210 .get_property = micro_batt_get_property,
211 .use_for_apm = 1,
212};
213
214static enum power_supply_property micro_ac_power_props[] = {
215 POWER_SUPPLY_PROP_ONLINE,
216};
217
218static struct power_supply micro_ac_power = {
219 .name = "ac",
220 .type = POWER_SUPPLY_TYPE_MAINS,
221 .properties = micro_ac_power_props,
222 .num_properties = ARRAY_SIZE(micro_ac_power_props),
223 .get_property = micro_ac_get_property,
224};
225
226static int micro_batt_probe(struct platform_device *pdev)
227{
228 struct micro_battery *mb;
229
230 mb = devm_kzalloc(&pdev->dev, sizeof(*mb), GFP_KERNEL);
231 if (!mb)
232 return -ENOMEM;
233
234 mb->micro = dev_get_drvdata(pdev->dev.parent);
235 mb->wq = create_singlethread_workqueue("ipaq-battery-wq");
236 INIT_DELAYED_WORK(&mb->update, micro_battery_work);
237 platform_set_drvdata(pdev, mb);
238 queue_delayed_work(mb->wq, &mb->update, 1);
239 power_supply_register(&pdev->dev, &micro_batt_power);
240 power_supply_register(&pdev->dev, &micro_ac_power);
241
242 dev_info(&pdev->dev, "iPAQ micro battery driver\n");
243 return 0;
244}
245
246static int micro_batt_remove(struct platform_device *pdev)
247
248{
249 struct micro_battery *mb = platform_get_drvdata(pdev);
250
251 power_supply_unregister(&micro_ac_power);
252 power_supply_unregister(&micro_batt_power);
253 cancel_delayed_work_sync(&mb->update);
254
255 return 0;
256}
257
258static int micro_batt_suspend(struct device *dev)
259{
260 struct micro_battery *mb = dev_get_drvdata(dev);
261
262 cancel_delayed_work_sync(&mb->update);
263 return 0;
264}
265
266static int micro_batt_resume(struct device *dev)
267{
268 struct micro_battery *mb = dev_get_drvdata(dev);
269
270 queue_delayed_work(mb->wq, &mb->update, msecs_to_jiffies(BATT_PERIOD));
271 return 0;
272}
273
274static const struct dev_pm_ops micro_batt_dev_pm_ops = {
275 SET_SYSTEM_SLEEP_PM_OPS(micro_batt_suspend, micro_batt_resume)
276};
277
278static struct platform_driver micro_batt_device_driver = {
279 .driver = {
280 .name = "ipaq-micro-battery",
281 .pm = &micro_batt_dev_pm_ops,
282 },
283 .probe = micro_batt_probe,
284 .remove = micro_batt_remove,
285};
286module_platform_driver(micro_batt_device_driver);
287
288MODULE_LICENSE("GPL");
289MODULE_DESCRIPTION("driver for iPAQ Atmel micro battery");
290MODULE_ALIAS("platform:battery-ipaq-micro");
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index 5a5a24e7d43c..078afd61490d 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -537,7 +537,8 @@ static void psy_unregister_cooler(struct power_supply *psy)
537} 537}
538#endif 538#endif
539 539
540int __power_supply_register(struct device *parent, struct power_supply *psy, bool ws) 540static int __power_supply_register(struct device *parent,
541 struct power_supply *psy, bool ws)
541{ 542{
542 struct device *dev; 543 struct device *dev;
543 int rc; 544 int rc;
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
index 44420d1e9094..750a20275664 100644
--- a/drivers/power/power_supply_sysfs.c
+++ b/drivers/power/power_supply_sysfs.c
@@ -167,6 +167,7 @@ static struct device_attribute power_supply_attrs[] = {
167 POWER_SUPPLY_ATTR(constant_charge_voltage_max), 167 POWER_SUPPLY_ATTR(constant_charge_voltage_max),
168 POWER_SUPPLY_ATTR(charge_control_limit), 168 POWER_SUPPLY_ATTR(charge_control_limit),
169 POWER_SUPPLY_ATTR(charge_control_limit_max), 169 POWER_SUPPLY_ATTR(charge_control_limit_max),
170 POWER_SUPPLY_ATTR(input_current_limit),
170 POWER_SUPPLY_ATTR(energy_full_design), 171 POWER_SUPPLY_ATTR(energy_full_design),
171 POWER_SUPPLY_ATTR(energy_empty_design), 172 POWER_SUPPLY_ATTR(energy_empty_design),
172 POWER_SUPPLY_ATTR(energy_full), 173 POWER_SUPPLY_ATTR(energy_full),
@@ -178,6 +179,8 @@ static struct device_attribute power_supply_attrs[] = {
178 POWER_SUPPLY_ATTR(capacity_alert_max), 179 POWER_SUPPLY_ATTR(capacity_alert_max),
179 POWER_SUPPLY_ATTR(capacity_level), 180 POWER_SUPPLY_ATTR(capacity_level),
180 POWER_SUPPLY_ATTR(temp), 181 POWER_SUPPLY_ATTR(temp),
182 POWER_SUPPLY_ATTR(temp_max),
183 POWER_SUPPLY_ATTR(temp_min),
181 POWER_SUPPLY_ATTR(temp_alert_min), 184 POWER_SUPPLY_ATTR(temp_alert_min),
182 POWER_SUPPLY_ATTR(temp_alert_max), 185 POWER_SUPPLY_ATTR(temp_alert_max),
183 POWER_SUPPLY_ATTR(temp_ambient), 186 POWER_SUPPLY_ATTR(temp_ambient),
@@ -189,6 +192,7 @@ static struct device_attribute power_supply_attrs[] = {
189 POWER_SUPPLY_ATTR(time_to_full_avg), 192 POWER_SUPPLY_ATTR(time_to_full_avg),
190 POWER_SUPPLY_ATTR(type), 193 POWER_SUPPLY_ATTR(type),
191 POWER_SUPPLY_ATTR(scope), 194 POWER_SUPPLY_ATTR(scope),
195 POWER_SUPPLY_ATTR(charge_term_current),
192 /* Properties of type `const char *' */ 196 /* Properties of type `const char *' */
193 POWER_SUPPLY_ATTR(model_name), 197 POWER_SUPPLY_ATTR(model_name),
194 POWER_SUPPLY_ATTR(manufacturer), 198 POWER_SUPPLY_ATTR(manufacturer),
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index bdcf5173e377..f2ac54df496f 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -20,6 +20,17 @@ config POWER_RESET_AXXIA
20 20
21 Say Y if you have an Axxia family SoC. 21 Say Y if you have an Axxia family SoC.
22 22
23config POWER_RESET_BRCMSTB
24 bool "Broadcom STB reset driver" if COMPILE_TEST
25 depends on POWER_RESET && ARM
26 default ARCH_BRCMSTB
27 help
28 This driver provides restart support for ARM-based Broadcom STB
29 boards.
30
31 Say Y here if you have an ARM-based Broadcom STB board and you wish
32 to have restart support.
33
23config POWER_RESET_GPIO 34config POWER_RESET_GPIO
24 bool "GPIO power-off driver" 35 bool "GPIO power-off driver"
25 depends on OF_GPIO && POWER_RESET 36 depends on OF_GPIO && POWER_RESET
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index dde2e8bbac53..7379818ca69d 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -1,5 +1,6 @@
1obj-$(CONFIG_POWER_RESET_AS3722) += as3722-poweroff.o 1obj-$(CONFIG_POWER_RESET_AS3722) += as3722-poweroff.o
2obj-$(CONFIG_POWER_RESET_AXXIA) += axxia-reset.o 2obj-$(CONFIG_POWER_RESET_AXXIA) += axxia-reset.o
3obj-$(CONFIG_POWER_RESET_BRCMSTB) += brcmstb-reboot.o
3obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o 4obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
4obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o 5obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o
5obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o 6obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o
diff --git a/drivers/power/reset/brcmstb-reboot.c b/drivers/power/reset/brcmstb-reboot.c
new file mode 100644
index 000000000000..3f236924742a
--- /dev/null
+++ b/drivers/power/reset/brcmstb-reboot.c
@@ -0,0 +1,120 @@
1/*
2 * Copyright (C) 2013 Broadcom Corporation
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation version 2.
7 *
8 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
9 * kind, whether express or implied; without even the implied warranty
10 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include <linux/device.h>
15#include <linux/errno.h>
16#include <linux/init.h>
17#include <linux/io.h>
18#include <linux/jiffies.h>
19#include <linux/of_address.h>
20#include <linux/of_irq.h>
21#include <linux/of_platform.h>
22#include <linux/platform_device.h>
23#include <linux/printk.h>
24#include <linux/reboot.h>
25#include <linux/regmap.h>
26#include <linux/smp.h>
27#include <linux/mfd/syscon.h>
28
29#include <asm/system_misc.h>
30
31#define RESET_SOURCE_ENABLE_REG 1
32#define SW_MASTER_RESET_REG 2
33
34static struct regmap *regmap;
35static u32 rst_src_en;
36static u32 sw_mstr_rst;
37
38static void brcmstb_reboot(enum reboot_mode mode, const char *cmd)
39{
40 int rc;
41 u32 tmp;
42
43 rc = regmap_write(regmap, rst_src_en, 1);
44 if (rc) {
45 pr_err("failed to write rst_src_en (%d)\n", rc);
46 return;
47 }
48
49 rc = regmap_read(regmap, rst_src_en, &tmp);
50 if (rc) {
51 pr_err("failed to read rst_src_en (%d)\n", rc);
52 return;
53 }
54
55 rc = regmap_write(regmap, sw_mstr_rst, 1);
56 if (rc) {
57 pr_err("failed to write sw_mstr_rst (%d)\n", rc);
58 return;
59 }
60
61 rc = regmap_read(regmap, sw_mstr_rst, &tmp);
62 if (rc) {
63 pr_err("failed to read sw_mstr_rst (%d)\n", rc);
64 return;
65 }
66
67 while (1)
68 ;
69}
70
71static int brcmstb_reboot_probe(struct platform_device *pdev)
72{
73 int rc;
74 struct device_node *np = pdev->dev.of_node;
75
76 regmap = syscon_regmap_lookup_by_phandle(np, "syscon");
77 if (IS_ERR(regmap)) {
78 pr_err("failed to get syscon phandle\n");
79 return -EINVAL;
80 }
81
82 rc = of_property_read_u32_index(np, "syscon", RESET_SOURCE_ENABLE_REG,
83 &rst_src_en);
84 if (rc) {
85 pr_err("can't get rst_src_en offset (%d)\n", rc);
86 return -EINVAL;
87 }
88
89 rc = of_property_read_u32_index(np, "syscon", SW_MASTER_RESET_REG,
90 &sw_mstr_rst);
91 if (rc) {
92 pr_err("can't get sw_mstr_rst offset (%d)\n", rc);
93 return -EINVAL;
94 }
95
96 arm_pm_restart = brcmstb_reboot;
97
98 return 0;
99}
100
101static const struct of_device_id of_match[] = {
102 { .compatible = "brcm,brcmstb-reboot", },
103 {},
104};
105
106static struct platform_driver brcmstb_reboot_driver = {
107 .probe = brcmstb_reboot_probe,
108 .driver = {
109 .name = "brcmstb-reboot",
110 .owner = THIS_MODULE,
111 .of_match_table = of_match,
112 },
113};
114
115static int __init brcmstb_reboot_init(void)
116{
117 return platform_driver_probe(&brcmstb_reboot_driver,
118 brcmstb_reboot_probe);
119}
120subsys_initcall(brcmstb_reboot_init);
diff --git a/drivers/power/reset/gpio-poweroff.c b/drivers/power/reset/gpio-poweroff.c
index e290d48ddd99..ce849bc9b269 100644
--- a/drivers/power/reset/gpio-poweroff.c
+++ b/drivers/power/reset/gpio-poweroff.c
@@ -15,31 +15,29 @@
15#include <linux/init.h> 15#include <linux/init.h>
16#include <linux/delay.h> 16#include <linux/delay.h>
17#include <linux/platform_device.h> 17#include <linux/platform_device.h>
18#include <linux/gpio.h> 18#include <linux/gpio/consumer.h>
19#include <linux/of_platform.h> 19#include <linux/of_platform.h>
20#include <linux/of_gpio.h>
21#include <linux/module.h> 20#include <linux/module.h>
22 21
23/* 22/*
24 * Hold configuration here, cannot be more than one instance of the driver 23 * Hold configuration here, cannot be more than one instance of the driver
25 * since pm_power_off itself is global. 24 * since pm_power_off itself is global.
26 */ 25 */
27static int gpio_num = -1; 26static struct gpio_desc *reset_gpio;
28static int gpio_active_low;
29 27
30static void gpio_poweroff_do_poweroff(void) 28static void gpio_poweroff_do_poweroff(void)
31{ 29{
32 BUG_ON(!gpio_is_valid(gpio_num)); 30 BUG_ON(!reset_gpio);
33 31
34 /* drive it active, also inactive->active edge */ 32 /* drive it active, also inactive->active edge */
35 gpio_direction_output(gpio_num, !gpio_active_low); 33 gpiod_direction_output(reset_gpio, 1);
36 mdelay(100); 34 mdelay(100);
37 /* drive inactive, also active->inactive edge */ 35 /* drive inactive, also active->inactive edge */
38 gpio_set_value(gpio_num, gpio_active_low); 36 gpiod_set_value(reset_gpio, 0);
39 mdelay(100); 37 mdelay(100);
40 38
41 /* drive it active, also inactive->active edge */ 39 /* drive it active, also inactive->active edge */
42 gpio_set_value(gpio_num, !gpio_active_low); 40 gpiod_set_value(reset_gpio, 1);
43 41
44 /* give it some time */ 42 /* give it some time */
45 mdelay(3000); 43 mdelay(3000);
@@ -49,54 +47,42 @@ static void gpio_poweroff_do_poweroff(void)
49 47
50static int gpio_poweroff_probe(struct platform_device *pdev) 48static int gpio_poweroff_probe(struct platform_device *pdev)
51{ 49{
52 enum of_gpio_flags flags;
53 bool input = false; 50 bool input = false;
54 int ret;
55 51
56 /* If a pm_power_off function has already been added, leave it alone */ 52 /* If a pm_power_off function has already been added, leave it alone */
57 if (pm_power_off != NULL) { 53 if (pm_power_off != NULL) {
58 pr_err("%s: pm_power_off function already registered", 54 dev_err(&pdev->dev,
55 "%s: pm_power_off function already registered",
59 __func__); 56 __func__);
60 return -EBUSY; 57 return -EBUSY;
61 } 58 }
62 59
63 gpio_num = of_get_gpio_flags(pdev->dev.of_node, 0, &flags); 60 reset_gpio = devm_gpiod_get(&pdev->dev, NULL);
64 if (!gpio_is_valid(gpio_num)) 61 if (IS_ERR(reset_gpio))
65 return gpio_num; 62 return PTR_ERR(reset_gpio);
66
67 gpio_active_low = flags & OF_GPIO_ACTIVE_LOW;
68 63
69 input = of_property_read_bool(pdev->dev.of_node, "input"); 64 input = of_property_read_bool(pdev->dev.of_node, "input");
70 65
71 ret = gpio_request(gpio_num, "poweroff-gpio");
72 if (ret) {
73 pr_err("%s: Could not get GPIO %d", __func__, gpio_num);
74 return ret;
75 }
76 if (input) { 66 if (input) {
77 if (gpio_direction_input(gpio_num)) { 67 if (gpiod_direction_input(reset_gpio)) {
78 pr_err("Could not set direction of GPIO %d to input", 68 dev_err(&pdev->dev,
79 gpio_num); 69 "Could not set direction of reset GPIO to input\n");
80 goto err; 70 return -ENODEV;
81 } 71 }
82 } else { 72 } else {
83 if (gpio_direction_output(gpio_num, gpio_active_low)) { 73 if (gpiod_direction_output(reset_gpio, 0)) {
84 pr_err("Could not set direction of GPIO %d", gpio_num); 74 dev_err(&pdev->dev,
85 goto err; 75 "Could not set direction of reset GPIO\n");
76 return -ENODEV;
86 } 77 }
87 } 78 }
88 79
89 pm_power_off = &gpio_poweroff_do_poweroff; 80 pm_power_off = &gpio_poweroff_do_poweroff;
90 return 0; 81 return 0;
91
92err:
93 gpio_free(gpio_num);
94 return -ENODEV;
95} 82}
96 83
97static int gpio_poweroff_remove(struct platform_device *pdev) 84static int gpio_poweroff_remove(struct platform_device *pdev)
98{ 85{
99 gpio_free(gpio_num);
100 if (pm_power_off == &gpio_poweroff_do_poweroff) 86 if (pm_power_off == &gpio_poweroff_do_poweroff)
101 pm_power_off = NULL; 87 pm_power_off = NULL;
102 88
diff --git a/drivers/power/reset/restart-poweroff.c b/drivers/power/reset/restart-poweroff.c
index 5758033e0c16..3e51f8d29bfe 100644
--- a/drivers/power/reset/restart-poweroff.c
+++ b/drivers/power/reset/restart-poweroff.c
@@ -62,5 +62,5 @@ module_platform_driver(restart_poweroff_driver);
62 62
63MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch"); 63MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch");
64MODULE_DESCRIPTION("restart poweroff driver"); 64MODULE_DESCRIPTION("restart poweroff driver");
65MODULE_LICENSE("GPLv2"); 65MODULE_LICENSE("GPL v2");
66MODULE_ALIAS("platform:poweroff-restart"); 66MODULE_ALIAS("platform:poweroff-restart");
diff --git a/drivers/power/rx51_battery.c b/drivers/power/rx51_battery.c
index 1bc5857b8bd5..d5a2acfb8821 100644
--- a/drivers/power/rx51_battery.c
+++ b/drivers/power/rx51_battery.c
@@ -24,34 +24,27 @@
24#include <linux/power_supply.h> 24#include <linux/power_supply.h>
25#include <linux/slab.h> 25#include <linux/slab.h>
26#include <linux/i2c/twl4030-madc.h> 26#include <linux/i2c/twl4030-madc.h>
27 27#include <linux/iio/consumer.h>
28/* RX51 specific channels */ 28#include <linux/of.h>
29#define TWL4030_MADC_BTEMP_RX51 TWL4030_MADC_ADCIN0
30#define TWL4030_MADC_BCI_RX51 TWL4030_MADC_ADCIN4
31 29
32struct rx51_device_info { 30struct rx51_device_info {
33 struct device *dev; 31 struct device *dev;
34 struct power_supply bat; 32 struct power_supply bat;
33 struct iio_channel *channel_temp;
34 struct iio_channel *channel_bsi;
35 struct iio_channel *channel_vbat;
35}; 36};
36 37
37/* 38/*
38 * Read ADCIN channel value, code copied from maemo kernel 39 * Read ADCIN channel value, code copied from maemo kernel
39 */ 40 */
40static int rx51_battery_read_adc(int channel) 41static int rx51_battery_read_adc(struct iio_channel *channel)
41{ 42{
42 struct twl4030_madc_request req; 43 int val, err;
43 44 err = iio_read_channel_average_raw(channel, &val);
44 req.channels = channel; 45 if (err < 0)
45 req.do_avg = 1; 46 return err;
46 req.method = TWL4030_MADC_SW1; 47 return val;
47 req.func_cb = NULL;
48 req.type = TWL4030_MADC_WAIT;
49 req.raw = true;
50
51 if (twl4030_madc_conversion(&req) <= 0)
52 return -ENODATA;
53
54 return req.rbuf[ffs(channel) - 1];
55} 48}
56 49
57/* 50/*
@@ -60,10 +53,12 @@ static int rx51_battery_read_adc(int channel)
60 */ 53 */
61static int rx51_battery_read_voltage(struct rx51_device_info *di) 54static int rx51_battery_read_voltage(struct rx51_device_info *di)
62{ 55{
63 int voltage = rx51_battery_read_adc(TWL4030_MADC_VBAT); 56 int voltage = rx51_battery_read_adc(di->channel_vbat);
64 57
65 if (voltage < 0) 58 if (voltage < 0) {
59 dev_err(di->dev, "Could not read ADC: %d\n", voltage);
66 return voltage; 60 return voltage;
61 }
67 62
68 return 1000 * (10000 * voltage / 1705); 63 return 1000 * (10000 * voltage / 1705);
69} 64}
@@ -112,7 +107,10 @@ static int rx51_battery_read_temperature(struct rx51_device_info *di)
112{ 107{
113 int min = 0; 108 int min = 0;
114 int max = ARRAY_SIZE(rx51_temp_table2) - 1; 109 int max = ARRAY_SIZE(rx51_temp_table2) - 1;
115 int raw = rx51_battery_read_adc(TWL4030_MADC_BTEMP_RX51); 110 int raw = rx51_battery_read_adc(di->channel_temp);
111
112 if (raw < 0)
113 dev_err(di->dev, "Could not read ADC: %d\n", raw);
116 114
117 /* Zero and negative values are undefined */ 115 /* Zero and negative values are undefined */
118 if (raw <= 0) 116 if (raw <= 0)
@@ -146,10 +144,12 @@ static int rx51_battery_read_temperature(struct rx51_device_info *di)
146 */ 144 */
147static int rx51_battery_read_capacity(struct rx51_device_info *di) 145static int rx51_battery_read_capacity(struct rx51_device_info *di)
148{ 146{
149 int capacity = rx51_battery_read_adc(TWL4030_MADC_BCI_RX51); 147 int capacity = rx51_battery_read_adc(di->channel_bsi);
150 148
151 if (capacity < 0) 149 if (capacity < 0) {
150 dev_err(di->dev, "Could not read ADC: %d\n", capacity);
152 return capacity; 151 return capacity;
152 }
153 153
154 return 1280 * (1200 * capacity)/(1024 - capacity); 154 return 1280 * (1200 * capacity)/(1024 - capacity);
155} 155}
@@ -213,17 +213,46 @@ static int rx51_battery_probe(struct platform_device *pdev)
213 213
214 platform_set_drvdata(pdev, di); 214 platform_set_drvdata(pdev, di);
215 215
216 di->dev = &pdev->dev;
216 di->bat.name = dev_name(&pdev->dev); 217 di->bat.name = dev_name(&pdev->dev);
217 di->bat.type = POWER_SUPPLY_TYPE_BATTERY; 218 di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
218 di->bat.properties = rx51_battery_props; 219 di->bat.properties = rx51_battery_props;
219 di->bat.num_properties = ARRAY_SIZE(rx51_battery_props); 220 di->bat.num_properties = ARRAY_SIZE(rx51_battery_props);
220 di->bat.get_property = rx51_battery_get_property; 221 di->bat.get_property = rx51_battery_get_property;
221 222
223 di->channel_temp = iio_channel_get(di->dev, "temp");
224 if (IS_ERR(di->channel_temp)) {
225 ret = PTR_ERR(di->channel_temp);
226 goto error;
227 }
228
229 di->channel_bsi = iio_channel_get(di->dev, "bsi");
230 if (IS_ERR(di->channel_bsi)) {
231 ret = PTR_ERR(di->channel_bsi);
232 goto error_channel_temp;
233 }
234
235 di->channel_vbat = iio_channel_get(di->dev, "vbat");
236 if (IS_ERR(di->channel_vbat)) {
237 ret = PTR_ERR(di->channel_vbat);
238 goto error_channel_bsi;
239 }
240
222 ret = power_supply_register(di->dev, &di->bat); 241 ret = power_supply_register(di->dev, &di->bat);
223 if (ret) 242 if (ret)
224 return ret; 243 goto error_channel_vbat;
225 244
226 return 0; 245 return 0;
246
247error_channel_vbat:
248 iio_channel_release(di->channel_vbat);
249error_channel_bsi:
250 iio_channel_release(di->channel_bsi);
251error_channel_temp:
252 iio_channel_release(di->channel_temp);
253error:
254
255 return ret;
227} 256}
228 257
229static int rx51_battery_remove(struct platform_device *pdev) 258static int rx51_battery_remove(struct platform_device *pdev)
@@ -232,15 +261,28 @@ static int rx51_battery_remove(struct platform_device *pdev)
232 261
233 power_supply_unregister(&di->bat); 262 power_supply_unregister(&di->bat);
234 263
264 iio_channel_release(di->channel_vbat);
265 iio_channel_release(di->channel_bsi);
266 iio_channel_release(di->channel_temp);
267
235 return 0; 268 return 0;
236} 269}
237 270
271#ifdef CONFIG_OF
272static const struct of_device_id n900_battery_of_match[] = {
273 {.compatible = "nokia,n900-battery", },
274 { },
275};
276MODULE_DEVICE_TABLE(of, n900_battery_of_match);
277#endif
278
238static struct platform_driver rx51_battery_driver = { 279static struct platform_driver rx51_battery_driver = {
239 .probe = rx51_battery_probe, 280 .probe = rx51_battery_probe,
240 .remove = rx51_battery_remove, 281 .remove = rx51_battery_remove,
241 .driver = { 282 .driver = {
242 .name = "rx51-battery", 283 .name = "rx51-battery",
243 .owner = THIS_MODULE, 284 .owner = THIS_MODULE,
285 .of_match_table = of_match_ptr(n900_battery_of_match),
244 }, 286 },
245}; 287};
246module_platform_driver(rx51_battery_driver); 288module_platform_driver(rx51_battery_driver);
diff --git a/drivers/power/tps65090-charger.c b/drivers/power/tps65090-charger.c
index 1685f63b9e5d..3e8ba97c8169 100644
--- a/drivers/power/tps65090-charger.c
+++ b/drivers/power/tps65090-charger.c
@@ -17,9 +17,11 @@
17 */ 17 */
18#include <linux/delay.h> 18#include <linux/delay.h>
19#include <linux/err.h> 19#include <linux/err.h>
20#include <linux/freezer.h>
20#include <linux/init.h> 21#include <linux/init.h>
21#include <linux/interrupt.h> 22#include <linux/interrupt.h>
22#include <linux/kernel.h> 23#include <linux/kernel.h>
24#include <linux/kthread.h>
23#include <linux/module.h> 25#include <linux/module.h>
24#include <linux/of_device.h> 26#include <linux/of_device.h>
25#include <linux/platform_device.h> 27#include <linux/platform_device.h>
@@ -32,11 +34,15 @@
32#define TPS65090_VACG BIT(1) 34#define TPS65090_VACG BIT(1)
33#define TPS65090_NOITERM BIT(5) 35#define TPS65090_NOITERM BIT(5)
34 36
37#define POLL_INTERVAL (HZ * 2) /* Used when no irq */
38
35struct tps65090_charger { 39struct tps65090_charger {
36 struct device *dev; 40 struct device *dev;
37 int ac_online; 41 int ac_online;
38 int prev_ac_online; 42 int prev_ac_online;
39 int irq; 43 int irq;
44 struct task_struct *poll_task;
45 bool passive_mode;
40 struct power_supply ac; 46 struct power_supply ac;
41 struct tps65090_platform_data *pdata; 47 struct tps65090_platform_data *pdata;
42}; 48};
@@ -49,6 +55,9 @@ static int tps65090_low_chrg_current(struct tps65090_charger *charger)
49{ 55{
50 int ret; 56 int ret;
51 57
58 if (charger->passive_mode)
59 return 0;
60
52 ret = tps65090_write(charger->dev->parent, TPS65090_REG_CG_CTRL5, 61 ret = tps65090_write(charger->dev->parent, TPS65090_REG_CG_CTRL5,
53 TPS65090_NOITERM); 62 TPS65090_NOITERM);
54 if (ret < 0) { 63 if (ret < 0) {
@@ -64,6 +73,9 @@ static int tps65090_enable_charging(struct tps65090_charger *charger)
64 int ret; 73 int ret;
65 uint8_t ctrl0 = 0; 74 uint8_t ctrl0 = 0;
66 75
76 if (charger->passive_mode)
77 return 0;
78
67 ret = tps65090_read(charger->dev->parent, TPS65090_REG_CG_CTRL0, 79 ret = tps65090_read(charger->dev->parent, TPS65090_REG_CG_CTRL0,
68 &ctrl0); 80 &ctrl0);
69 if (ret < 0) { 81 if (ret < 0) {
@@ -87,6 +99,9 @@ static int tps65090_config_charger(struct tps65090_charger *charger)
87 uint8_t intrmask = 0; 99 uint8_t intrmask = 0;
88 int ret; 100 int ret;
89 101
102 if (charger->passive_mode)
103 return 0;
104
90 if (charger->pdata->enable_low_current_chrg) { 105 if (charger->pdata->enable_low_current_chrg) {
91 ret = tps65090_low_chrg_current(charger); 106 ret = tps65090_low_chrg_current(charger);
92 if (ret < 0) { 107 if (ret < 0) {
@@ -164,10 +179,14 @@ static irqreturn_t tps65090_charger_isr(int irq, void *dev_id)
164 } 179 }
165 180
166 /* Clear interrupts. */ 181 /* Clear interrupts. */
167 ret = tps65090_write(charger->dev->parent, TPS65090_REG_INTR_STS, 0x00); 182 if (!charger->passive_mode) {
168 if (ret < 0) { 183 ret = tps65090_write(charger->dev->parent,
169 dev_err(charger->dev, "%s(): Error in writing reg 0x%x\n", 184 TPS65090_REG_INTR_STS, 0x00);
185 if (ret < 0) {
186 dev_err(charger->dev,
187 "%s(): Error in writing reg 0x%x\n",
170 __func__, TPS65090_REG_INTR_STS); 188 __func__, TPS65090_REG_INTR_STS);
189 }
171 } 190 }
172 191
173 if (charger->prev_ac_online != charger->ac_online) 192 if (charger->prev_ac_online != charger->ac_online)
@@ -198,6 +217,18 @@ static struct tps65090_platform_data *
198 217
199} 218}
200 219
220static int tps65090_charger_poll_task(void *data)
221{
222 set_freezable();
223
224 while (!kthread_should_stop()) {
225 schedule_timeout_interruptible(POLL_INTERVAL);
226 try_to_freeze();
227 tps65090_charger_isr(-1, data);
228 }
229 return 0;
230}
231
201static int tps65090_charger_probe(struct platform_device *pdev) 232static int tps65090_charger_probe(struct platform_device *pdev)
202{ 233{
203 struct tps65090_charger *cdata; 234 struct tps65090_charger *cdata;
@@ -244,22 +275,10 @@ static int tps65090_charger_probe(struct platform_device *pdev)
244 } 275 }
245 276
246 irq = platform_get_irq(pdev, 0); 277 irq = platform_get_irq(pdev, 0);
247 if (irq <= 0) { 278 if (irq < 0)
248 dev_warn(&pdev->dev, "Unable to get charger irq = %d\n", irq); 279 irq = -ENXIO;
249 ret = irq;
250 goto fail_unregister_supply;
251 }
252
253 cdata->irq = irq; 280 cdata->irq = irq;
254 281
255 ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
256 tps65090_charger_isr, 0, "tps65090-charger", cdata);
257 if (ret) {
258 dev_err(cdata->dev, "Unable to register irq %d err %d\n", irq,
259 ret);
260 goto fail_unregister_supply;
261 }
262
263 ret = tps65090_config_charger(cdata); 282 ret = tps65090_config_charger(cdata);
264 if (ret < 0) { 283 if (ret < 0) {
265 dev_err(&pdev->dev, "charger config failed, err %d\n", ret); 284 dev_err(&pdev->dev, "charger config failed, err %d\n", ret);
@@ -285,6 +304,27 @@ static int tps65090_charger_probe(struct platform_device *pdev)
285 power_supply_changed(&cdata->ac); 304 power_supply_changed(&cdata->ac);
286 } 305 }
287 306
307 if (irq != -ENXIO) {
308 ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
309 tps65090_charger_isr, 0, "tps65090-charger", cdata);
310 if (ret) {
311 dev_err(cdata->dev,
312 "Unable to register irq %d err %d\n", irq,
313 ret);
314 goto fail_unregister_supply;
315 }
316 } else {
317 cdata->poll_task = kthread_run(tps65090_charger_poll_task,
318 cdata, "ktps65090charger");
319 cdata->passive_mode = true;
320 if (IS_ERR(cdata->poll_task)) {
321 ret = PTR_ERR(cdata->poll_task);
322 dev_err(cdata->dev,
323 "Unable to run kthread err %d\n", ret);
324 goto fail_unregister_supply;
325 }
326 }
327
288 return 0; 328 return 0;
289 329
290fail_unregister_supply: 330fail_unregister_supply:
@@ -297,6 +337,8 @@ static int tps65090_charger_remove(struct platform_device *pdev)
297{ 337{
298 struct tps65090_charger *cdata = platform_get_drvdata(pdev); 338 struct tps65090_charger *cdata = platform_get_drvdata(pdev);
299 339
340 if (cdata->irq == -ENXIO)
341 kthread_stop(cdata->poll_task);
300 power_supply_unregister(&cdata->ac); 342 power_supply_unregister(&cdata->ac);
301 343
302 return 0; 344 return 0;
diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index f14108844e1a..2598c588006e 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -28,10 +28,13 @@
28#define TWL4030_BCIICHG 0x08 28#define TWL4030_BCIICHG 0x08
29#define TWL4030_BCIVAC 0x0a 29#define TWL4030_BCIVAC 0x0a
30#define TWL4030_BCIVBUS 0x0c 30#define TWL4030_BCIVBUS 0x0c
31#define TWL4030_BCIMFSTS3 0x0F
31#define TWL4030_BCIMFSTS4 0x10 32#define TWL4030_BCIMFSTS4 0x10
32#define TWL4030_BCICTL1 0x23 33#define TWL4030_BCICTL1 0x23
33#define TWL4030_BB_CFG 0x12 34#define TWL4030_BB_CFG 0x12
34 35
36#define TWL4030_BCIMFSTS1 0x01
37
35#define TWL4030_BCIAUTOWEN BIT(5) 38#define TWL4030_BCIAUTOWEN BIT(5)
36#define TWL4030_CONFIG_DONE BIT(4) 39#define TWL4030_CONFIG_DONE BIT(4)
37#define TWL4030_BCIAUTOUSB BIT(1) 40#define TWL4030_BCIAUTOUSB BIT(1)
@@ -52,6 +55,9 @@
52#define TWL4030_BBISEL_500uA 0x02 55#define TWL4030_BBISEL_500uA 0x02
53#define TWL4030_BBISEL_1000uA 0x03 56#define TWL4030_BBISEL_1000uA 0x03
54 57
58#define TWL4030_BATSTSPCHG BIT(2)
59#define TWL4030_BATSTSMCHG BIT(6)
60
55/* BCI interrupts */ 61/* BCI interrupts */
56#define TWL4030_WOVF BIT(0) /* Watchdog overflow */ 62#define TWL4030_WOVF BIT(0) /* Watchdog overflow */
57#define TWL4030_TMOVF BIT(1) /* Timer overflow */ 63#define TWL4030_TMOVF BIT(1) /* Timer overflow */
@@ -145,6 +151,35 @@ static int twl4030bci_read_adc_val(u8 reg)
145} 151}
146 152
147/* 153/*
154 * Check if Battery Pack was present
155 */
156static int twl4030_is_battery_present(struct twl4030_bci *bci)
157{
158 int ret;
159 u8 val = 0;
160
161 /* Battery presence in Main charge? */
162 ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE, &val, TWL4030_BCIMFSTS3);
163 if (ret)
164 return ret;
165 if (val & TWL4030_BATSTSMCHG)
166 return 0;
167
168 /*
169 * OK, It could be that bootloader did not enable main charger,
170 * pre-charge is h/w auto. So, Battery presence in Pre-charge?
171 */
172 ret = twl_i2c_read_u8(TWL4030_MODULE_PRECHARGE, &val,
173 TWL4030_BCIMFSTS1);
174 if (ret)
175 return ret;
176 if (val & TWL4030_BATSTSPCHG)
177 return 0;
178
179 return -ENODEV;
180}
181
182/*
148 * Check if VBUS power is present 183 * Check if VBUS power is present
149 */ 184 */
150static int twl4030_bci_have_vbus(struct twl4030_bci *bci) 185static int twl4030_bci_have_vbus(struct twl4030_bci *bci)
@@ -541,8 +576,14 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
541 bci->irq_chg = platform_get_irq(pdev, 0); 576 bci->irq_chg = platform_get_irq(pdev, 0);
542 bci->irq_bci = platform_get_irq(pdev, 1); 577 bci->irq_bci = platform_get_irq(pdev, 1);
543 578
544 platform_set_drvdata(pdev, bci); 579 /* Only proceed further *IF* battery is physically present */
580 ret = twl4030_is_battery_present(bci);
581 if (ret) {
582 dev_crit(&pdev->dev, "Battery was not detected:%d\n", ret);
583 goto fail_no_battery;
584 }
545 585
586 platform_set_drvdata(pdev, bci);
546 bci->ac.name = "twl4030_ac"; 587 bci->ac.name = "twl4030_ac";
547 bci->ac.type = POWER_SUPPLY_TYPE_MAINS; 588 bci->ac.type = POWER_SUPPLY_TYPE_MAINS;
548 bci->ac.properties = twl4030_charger_props; 589 bci->ac.properties = twl4030_charger_props;
@@ -633,6 +674,7 @@ fail_chg_irq:
633fail_register_usb: 674fail_register_usb:
634 power_supply_unregister(&bci->ac); 675 power_supply_unregister(&bci->ac);
635fail_register_ac: 676fail_register_ac:
677fail_no_battery:
636 kfree(bci); 678 kfree(bci);
637 679
638 return ret; 680 return ret;
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index f2b76aeaf4e4..f3dea41dbcd2 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -120,6 +120,7 @@ enum power_supply_property {
120 POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX, 120 POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
121 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT, 121 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT,
122 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX, 122 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX,
123 POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
123 POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, 124 POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
124 POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN, 125 POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN,
125 POWER_SUPPLY_PROP_ENERGY_FULL, 126 POWER_SUPPLY_PROP_ENERGY_FULL,
@@ -131,6 +132,8 @@ enum power_supply_property {
131 POWER_SUPPLY_PROP_CAPACITY_ALERT_MAX, /* in percents! */ 132 POWER_SUPPLY_PROP_CAPACITY_ALERT_MAX, /* in percents! */
132 POWER_SUPPLY_PROP_CAPACITY_LEVEL, 133 POWER_SUPPLY_PROP_CAPACITY_LEVEL,
133 POWER_SUPPLY_PROP_TEMP, 134 POWER_SUPPLY_PROP_TEMP,
135 POWER_SUPPLY_PROP_TEMP_MAX,
136 POWER_SUPPLY_PROP_TEMP_MIN,
134 POWER_SUPPLY_PROP_TEMP_ALERT_MIN, 137 POWER_SUPPLY_PROP_TEMP_ALERT_MIN,
135 POWER_SUPPLY_PROP_TEMP_ALERT_MAX, 138 POWER_SUPPLY_PROP_TEMP_ALERT_MAX,
136 POWER_SUPPLY_PROP_TEMP_AMBIENT, 139 POWER_SUPPLY_PROP_TEMP_AMBIENT,
@@ -142,6 +145,7 @@ enum power_supply_property {
142 POWER_SUPPLY_PROP_TIME_TO_FULL_AVG, 145 POWER_SUPPLY_PROP_TIME_TO_FULL_AVG,
143 POWER_SUPPLY_PROP_TYPE, /* use power_supply.type instead */ 146 POWER_SUPPLY_PROP_TYPE, /* use power_supply.type instead */
144 POWER_SUPPLY_PROP_SCOPE, 147 POWER_SUPPLY_PROP_SCOPE,
148 POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT,
145 /* Properties of type `const char *' */ 149 /* Properties of type `const char *' */
146 POWER_SUPPLY_PROP_MODEL_NAME, 150 POWER_SUPPLY_PROP_MODEL_NAME,
147 POWER_SUPPLY_PROP_MANUFACTURER, 151 POWER_SUPPLY_PROP_MANUFACTURER,