aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-01-21 14:36:20 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-01-21 14:36:20 -0500
commit03d11a0e458d7008192585124e4c3313c2829046 (patch)
tree8e9f5141e53d2d4bf435fbd56f8ae96790304b7f
parentac26663572db5b64522b92f3941a58678a832a36 (diff)
parent573189354b7c97cd2256b87cf083ee435584594e (diff)
Merge tag 'for-v3.14' of git://git.infradead.org/battery-2.6
Pull battery updates from Dmitry Eremin-Solenikov: "I'm picking up power supply maintainership from Anton Vorontov. Could you please pull battery-2.6 git tree changes prepared for the v3.14 release. Highlights: - Power supply notifier - Several drivers gained DT support - Added Maxim 14577 driver - Change of maintainer" * tag 'for-v3.14' of git://git.infradead.org/battery-2.6: MAINTAINERS: Pick up power supply maintainership max17042_battery: Add IRQF_ONESHOT flag to use default irq handler gpio-charger: Support wakeup events power_supply: Add charger support for Maxim 14577 dt: Binding documentation for isp1704 charger isp1704_charger: Add DT support charger-manager: of_cm_parse_desc() should be static bq2415x_charger: Add DT support power_supply: Add power_supply_get_by_phandle bq2415x_charger: Use power_supply notifier for automode power: reset: Add as3722 power-off driver mfd: AS3722: Add dt node properties for system power controller charger-manager: Support deivce tree in charger manager driver charger-manager: Modify the way of checking battery's temperature power_supply: Add power_supply notifier
-rw-r--r--Documentation/devicetree/bindings/mfd/as3722.txt11
-rw-r--r--Documentation/devicetree/bindings/power/isp1704.txt17
-rw-r--r--Documentation/devicetree/bindings/power_supply/charger-manager.txt81
-rw-r--r--MAINTAINERS2
-rw-r--r--drivers/power/Kconfig7
-rw-r--r--drivers/power/Makefile1
-rw-r--r--drivers/power/bq2415x_charger.c121
-rw-r--r--drivers/power/charger-manager.c299
-rw-r--r--drivers/power/gpio-charger.c19
-rw-r--r--drivers/power/isp1704_charger.c54
-rw-r--r--drivers/power/max14577_charger.c311
-rw-r--r--drivers/power/max17042_battery.c6
-rw-r--r--drivers/power/power_supply_core.c44
-rw-r--r--drivers/power/reset/Kconfig6
-rw-r--r--drivers/power/reset/Makefile1
-rw-r--r--drivers/power/reset/as3722-poweroff.c96
-rw-r--r--include/linux/power/bq2415x_charger.h48
-rw-r--r--include/linux/power/charger-manager.h34
-rw-r--r--include/linux/power/isp1704_charger.h1
-rw-r--r--include/linux/power_supply.h16
20 files changed, 1043 insertions, 132 deletions
diff --git a/Documentation/devicetree/bindings/mfd/as3722.txt b/Documentation/devicetree/bindings/mfd/as3722.txt
index fc2191ecfd6b..8edcb9bd873b 100644
--- a/Documentation/devicetree/bindings/mfd/as3722.txt
+++ b/Documentation/devicetree/bindings/mfd/as3722.txt
@@ -112,6 +112,15 @@ Following are properties of regulator subnode.
112 ams,enable-tracking: Enable tracking with SD1, only supported 112 ams,enable-tracking: Enable tracking with SD1, only supported
113 by LDO3. 113 by LDO3.
114 114
115Power-off:
116=========
117AS3722 supports the system power off by turning off all its rail. This
118is provided through pm_power_off.
119The device node should have the following properties to enable this
120functionality
121ams,system-power-controller: Boolean, to enable the power off functionality
122 through this device.
123
115Example: 124Example:
116-------- 125--------
117#include <dt-bindings/mfd/as3722.h> 126#include <dt-bindings/mfd/as3722.h>
@@ -120,6 +129,8 @@ ams3722 {
120 compatible = "ams,as3722"; 129 compatible = "ams,as3722";
121 reg = <0x48>; 130 reg = <0x48>;
122 131
132 ams,system-power-controller;
133
123 interrupt-parent = <&intc>; 134 interrupt-parent = <&intc>;
124 interrupt-controller; 135 interrupt-controller;
125 #interrupt-cells = <2>; 136 #interrupt-cells = <2>;
diff --git a/Documentation/devicetree/bindings/power/isp1704.txt b/Documentation/devicetree/bindings/power/isp1704.txt
new file mode 100644
index 000000000000..fa3596907967
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/isp1704.txt
@@ -0,0 +1,17 @@
1Binding for NXP ISP1704 USB Charger Detection
2
3Required properties:
4- compatible: Should contain one of the following:
5 * "nxp,isp1704"
6- nxp,enable-gpio: Should contain a phandle + gpio-specifier
7 to the GPIO pin connected to the chip's enable pin.
8- usb-phy: Should contain a phandle to the USB PHY
9 the ISP1704 is connected to.
10
11Example:
12
13isp1704 {
14 compatible = "nxp,isp1704";
15 nxp,enable-gpio = <&gpio3 3 GPIO_ACTIVE_LOW>;
16 usb-phy = <&usb2_phy>;
17};
diff --git a/Documentation/devicetree/bindings/power_supply/charger-manager.txt b/Documentation/devicetree/bindings/power_supply/charger-manager.txt
new file mode 100644
index 000000000000..2b33750e3db2
--- /dev/null
+++ b/Documentation/devicetree/bindings/power_supply/charger-manager.txt
@@ -0,0 +1,81 @@
1charger-manager bindings
2~~~~~~~~~~~~~~~~~~~~~~~~
3
4Required properties :
5 - compatible : "charger-manager"
6 - <>-supply : for regulator consumer
7 - cm-num-chargers : number of chargers
8 - cm-chargers : name of chargers
9 - cm-fuel-gauge : name of battery fuel gauge
10 - subnode <regulator> :
11 - cm-regulator-name : name of charger regulator
12 - subnode <cable> :
13 - cm-cable-name : name of charger cable
14 - cm-cable-extcon : name of extcon dev
15(optional) - cm-cable-min : minimum current of cable
16(optional) - cm-cable-max : maximum current of cable
17
18Optional properties :
19 - cm-name : charger manager's name (default : "battery")
20 - cm-poll-mode : polling mode (enum polling_modes)
21 - cm-poll-interval : polling interval
22 - cm-battery-stat : battery status (enum data_source)
23 - cm-fullbatt-* : data for full battery checking
24 - cm-thermal-zone : name of external thermometer's thermal zone
25 - cm-battery-* : threshold battery temperature for charging
26 -cold : critical cold temperature of battery for charging
27 -cold-in-minus : flag that cold temerature is in minus degree
28 -hot : critical hot temperature of battery for charging
29 -temp-diff : temperature difference to allow recharging
30 - cm-dis/charging-max = limits of charging duration
31
32Example :
33 charger-manager@0 {
34 compatible = "charger-manager";
35 chg-reg-supply = <&charger_regulator>;
36
37 cm-name = "battery";
38 /* Always polling ON : 30s */
39 cm-poll-mode = <1>;
40 cm-poll-interval = <30000>;
41
42 cm-fullbatt-vchkdrop-ms = <30000>;
43 cm-fullbatt-vchkdrop-volt = <150000>;
44 cm-fullbatt-soc = <100>;
45
46 cm-battery-stat = <3>;
47
48 cm-num-chargers = <3>;
49 cm-chargers = "charger0", "charger1", "charger2";
50
51 cm-fuel-gauge = "fuelgauge0";
52
53 cm-thermal-zone = "thermal_zone.1"
54 /* in deci centigrade */
55 cm-battery-cold = <50>;
56 cm-battery-cold-in-minus;
57 cm-battery-hot = <800>;
58 cm-battery-temp-diff = <100>;
59
60 /* Allow charging for 5hr */
61 cm-charging-max = <18000000>;
62 /* Allow discharging for 2hr */
63 cm-discharging-max = <7200000>;
64
65 regulator@0 {
66 cm-regulator-name = "chg-reg";
67 cable@0 {
68 cm-cable-name = "USB";
69 cm-cable-extcon = "extcon-dev.0";
70 cm-cable-min = <475000>;
71 cm-cable-max = <500000>;
72 };
73 cable@1 {
74 cm-cable-name = "TA";
75 cm-cable-extcon = "extcon-dev.0";
76 cm-cable-min = <650000>;
77 cm-cable-max = <675000>;
78 };
79 };
80
81 };
diff --git a/MAINTAINERS b/MAINTAINERS
index 5c214024f60a..1088b70fbad7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6712,7 +6712,7 @@ F: include/linux/timer*
6712F: kernel/*timer* 6712F: kernel/*timer*
6713 6713
6714POWER SUPPLY CLASS/SUBSYSTEM and DRIVERS 6714POWER SUPPLY CLASS/SUBSYSTEM and DRIVERS
6715M: Anton Vorontsov <anton@enomsg.org> 6715M: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
6716M: David Woodhouse <dwmw2@infradead.org> 6716M: David Woodhouse <dwmw2@infradead.org>
6717T: git git://git.infradead.org/battery-2.6.git 6717T: git git://git.infradead.org/battery-2.6.git
6718S: Maintained 6718S: Maintained
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 85ad58c6da17..0196acf05231 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -317,6 +317,13 @@ config CHARGER_MANAGER
317 runtime and in suspend-to-RAM by waking up the system periodically 317 runtime and in suspend-to-RAM by waking up the system periodically
318 with help of suspend_again support. 318 with help of suspend_again support.
319 319
320config CHARGER_MAX14577
321 tristate "Maxim MAX14577 MUIC battery charger driver"
322 depends on MFD_MAX14577
323 help
324 Say Y to enable support for the battery charger control sysfs and
325 platform data of MAX14577 MUICs.
326
320config CHARGER_MAX8997 327config CHARGER_MAX8997
321 tristate "Maxim MAX8997/MAX8966 PMIC battery charger driver" 328 tristate "Maxim MAX8997/MAX8966 PMIC battery charger driver"
322 depends on MFD_MAX8997 && REGULATOR_MAX8997 329 depends on MFD_MAX8997 && REGULATOR_MAX8997
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 372b4e8ab598..ee54a3e4c90a 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -48,6 +48,7 @@ obj-$(CONFIG_CHARGER_LP8727) += lp8727_charger.o
48obj-$(CONFIG_CHARGER_LP8788) += lp8788-charger.o 48obj-$(CONFIG_CHARGER_LP8788) += lp8788-charger.o
49obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o 49obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o
50obj-$(CONFIG_CHARGER_MANAGER) += charger-manager.o 50obj-$(CONFIG_CHARGER_MANAGER) += charger-manager.o
51obj-$(CONFIG_CHARGER_MAX14577) += max14577_charger.o
51obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o 52obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o
52obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o 53obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o
53obj-$(CONFIG_CHARGER_BQ2415X) += bq2415x_charger.o 54obj-$(CONFIG_CHARGER_BQ2415X) += bq2415x_charger.o
diff --git a/drivers/power/bq2415x_charger.c b/drivers/power/bq2415x_charger.c
index df893dd1447d..79a37f6d3307 100644
--- a/drivers/power/bq2415x_charger.c
+++ b/drivers/power/bq2415x_charger.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * bq2415x charger driver 2 * bq2415x charger driver
3 * 3 *
4 * Copyright (C) 2011-2012 Pali Rohár <pali.rohar@gmail.com> 4 * Copyright (C) 2011-2013 Pali Rohár <pali.rohar@gmail.com>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by 7 * it under the terms of the GNU General Public License as published by
@@ -170,6 +170,8 @@ struct bq2415x_device {
170 struct bq2415x_platform_data init_data; 170 struct bq2415x_platform_data init_data;
171 struct power_supply charger; 171 struct power_supply charger;
172 struct delayed_work work; 172 struct delayed_work work;
173 struct power_supply *notify_psy;
174 struct notifier_block nb;
173 enum bq2415x_mode reported_mode;/* mode reported by hook function */ 175 enum bq2415x_mode reported_mode;/* mode reported by hook function */
174 enum bq2415x_mode mode; /* current configured mode */ 176 enum bq2415x_mode mode; /* current configured mode */
175 enum bq2415x_chip chip; 177 enum bq2415x_chip chip;
@@ -795,24 +797,53 @@ static int bq2415x_set_mode(struct bq2415x_device *bq, enum bq2415x_mode mode)
795 797
796} 798}
797 799
798/* hook function called by other driver which set reported mode */ 800static int bq2415x_notifier_call(struct notifier_block *nb,
799static void bq2415x_hook_function(enum bq2415x_mode mode, void *data) 801 unsigned long val, void *v)
800{ 802{
801 struct bq2415x_device *bq = data; 803 struct bq2415x_device *bq =
804 container_of(nb, struct bq2415x_device, nb);
805 struct power_supply *psy = v;
806 enum bq2415x_mode mode;
807 union power_supply_propval prop;
808 int ret;
809 int mA;
802 810
803 if (!bq) 811 if (val != PSY_EVENT_PROP_CHANGED)
804 return; 812 return NOTIFY_OK;
813
814 if (psy != bq->notify_psy)
815 return NOTIFY_OK;
816
817 dev_dbg(bq->dev, "notifier call was called\n");
818
819 ret = psy->get_property(psy, POWER_SUPPLY_PROP_CURRENT_MAX, &prop);
820 if (ret != 0)
821 return NOTIFY_OK;
822
823 mA = prop.intval;
824
825 if (mA == 0)
826 mode = BQ2415X_MODE_OFF;
827 else if (mA < 500)
828 mode = BQ2415X_MODE_NONE;
829 else if (mA < 1800)
830 mode = BQ2415X_MODE_HOST_CHARGER;
831 else
832 mode = BQ2415X_MODE_DEDICATED_CHARGER;
833
834 if (bq->reported_mode == mode)
835 return NOTIFY_OK;
805 836
806 dev_dbg(bq->dev, "hook function was called\n");
807 bq->reported_mode = mode; 837 bq->reported_mode = mode;
808 838
809 /* if automode is not enabled do not tell about reported_mode */ 839 /* if automode is not enabled do not tell about reported_mode */
810 if (bq->automode < 1) 840 if (bq->automode < 1)
811 return; 841 return NOTIFY_OK;
812 842
813 sysfs_notify(&bq->charger.dev->kobj, NULL, "reported_mode"); 843 sysfs_notify(&bq->charger.dev->kobj, NULL, "reported_mode");
814 bq2415x_set_mode(bq, bq->reported_mode); 844 bq2415x_set_mode(bq, bq->reported_mode);
815 845
846 return NOTIFY_OK;
816} 847}
817 848
818/**** timer functions ****/ 849/**** timer functions ****/
@@ -1512,9 +1543,11 @@ static int bq2415x_probe(struct i2c_client *client,
1512 int num; 1543 int num;
1513 char *name; 1544 char *name;
1514 struct bq2415x_device *bq; 1545 struct bq2415x_device *bq;
1546 struct device_node *np = client->dev.of_node;
1547 struct bq2415x_platform_data *pdata = client->dev.platform_data;
1515 1548
1516 if (!client->dev.platform_data) { 1549 if (!np && !pdata) {
1517 dev_err(&client->dev, "platform data not set\n"); 1550 dev_err(&client->dev, "platform data missing\n");
1518 return -ENODEV; 1551 return -ENODEV;
1519 } 1552 }
1520 1553
@@ -1539,6 +1572,17 @@ static int bq2415x_probe(struct i2c_client *client,
1539 goto error_2; 1572 goto error_2;
1540 } 1573 }
1541 1574
1575 if (np) {
1576 bq->notify_psy = power_supply_get_by_phandle(np, "ti,usb-charger-detection");
1577
1578 if (!bq->notify_psy)
1579 return -EPROBE_DEFER;
1580 }
1581 else if (pdata->notify_device)
1582 bq->notify_psy = power_supply_get_by_name(pdata->notify_device);
1583 else
1584 bq->notify_psy = NULL;
1585
1542 i2c_set_clientdata(client, bq); 1586 i2c_set_clientdata(client, bq);
1543 1587
1544 bq->id = num; 1588 bq->id = num;
@@ -1550,8 +1594,34 @@ static int bq2415x_probe(struct i2c_client *client,
1550 bq->autotimer = 0; 1594 bq->autotimer = 0;
1551 bq->automode = 0; 1595 bq->automode = 0;
1552 1596
1553 memcpy(&bq->init_data, client->dev.platform_data, 1597 if (np) {
1554 sizeof(bq->init_data)); 1598 ret = of_property_read_u32(np, "ti,current-limit",
1599 &bq->init_data.current_limit);
1600 if (ret)
1601 return ret;
1602 ret = of_property_read_u32(np, "ti,weak-battery-voltage",
1603 &bq->init_data.weak_battery_voltage);
1604 if (ret)
1605 return ret;
1606 ret = of_property_read_u32(np, "ti,battery-regulation-voltage",
1607 &bq->init_data.battery_regulation_voltage);
1608 if (ret)
1609 return ret;
1610 ret = of_property_read_u32(np, "ti,charge-current",
1611 &bq->init_data.charge_current);
1612 if (ret)
1613 return ret;
1614 ret = of_property_read_u32(np, "ti,termination-current",
1615 &bq->init_data.termination_current);
1616 if (ret)
1617 return ret;
1618 ret = of_property_read_u32(np, "ti,resistor-sense",
1619 &bq->init_data.resistor_sense);
1620 if (ret)
1621 return ret;
1622 } else {
1623 memcpy(&bq->init_data, pdata, sizeof(bq->init_data));
1624 }
1555 1625
1556 bq2415x_reset_chip(bq); 1626 bq2415x_reset_chip(bq);
1557 1627
@@ -1573,16 +1643,20 @@ static int bq2415x_probe(struct i2c_client *client,
1573 goto error_4; 1643 goto error_4;
1574 } 1644 }
1575 1645
1576 if (bq->init_data.set_mode_hook) { 1646 if (bq->notify_psy) {
1577 if (bq->init_data.set_mode_hook( 1647 bq->nb.notifier_call = bq2415x_notifier_call;
1578 bq2415x_hook_function, bq)) { 1648 ret = power_supply_reg_notifier(&bq->nb);
1579 bq->automode = 1; 1649 if (ret) {
1580 bq2415x_set_mode(bq, bq->reported_mode); 1650 dev_err(bq->dev, "failed to reg notifier: %d\n", ret);
1581 dev_info(bq->dev, "automode enabled\n"); 1651 goto error_5;
1582 } else {
1583 bq->automode = -1;
1584 dev_info(bq->dev, "automode failed\n");
1585 } 1652 }
1653
1654 /* Query for initial reported_mode and set it */
1655 bq2415x_notifier_call(&bq->nb, PSY_EVENT_PROP_CHANGED, bq->notify_psy);
1656 bq2415x_set_mode(bq, bq->reported_mode);
1657
1658 bq->automode = 1;
1659 dev_info(bq->dev, "automode enabled\n");
1586 } else { 1660 } else {
1587 bq->automode = -1; 1661 bq->automode = -1;
1588 dev_info(bq->dev, "automode not supported\n"); 1662 dev_info(bq->dev, "automode not supported\n");
@@ -1594,6 +1668,7 @@ static int bq2415x_probe(struct i2c_client *client,
1594 dev_info(bq->dev, "driver registered\n"); 1668 dev_info(bq->dev, "driver registered\n");
1595 return 0; 1669 return 0;
1596 1670
1671error_5:
1597error_4: 1672error_4:
1598 bq2415x_sysfs_exit(bq); 1673 bq2415x_sysfs_exit(bq);
1599error_3: 1674error_3:
@@ -1614,8 +1689,8 @@ static int bq2415x_remove(struct i2c_client *client)
1614{ 1689{
1615 struct bq2415x_device *bq = i2c_get_clientdata(client); 1690 struct bq2415x_device *bq = i2c_get_clientdata(client);
1616 1691
1617 if (bq->init_data.set_mode_hook) 1692 if (bq->notify_psy)
1618 bq->init_data.set_mode_hook(NULL, NULL); 1693 power_supply_unreg_notifier(&bq->nb);
1619 1694
1620 bq2415x_sysfs_exit(bq); 1695 bq2415x_sysfs_exit(bq);
1621 bq2415x_power_supply_exit(bq); 1696 bq2415x_power_supply_exit(bq);
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 7287c0efd6bf..9e4dab46eefd 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -25,12 +25,23 @@
25#include <linux/power/charger-manager.h> 25#include <linux/power/charger-manager.h>
26#include <linux/regulator/consumer.h> 26#include <linux/regulator/consumer.h>
27#include <linux/sysfs.h> 27#include <linux/sysfs.h>
28#include <linux/of.h>
29#include <linux/thermal.h>
30
31/*
32 * Default termperature threshold for charging.
33 * Every temperature units are in tenth of centigrade.
34 */
35#define CM_DEFAULT_RECHARGE_TEMP_DIFF 50
36#define CM_DEFAULT_CHARGE_TEMP_MAX 500
28 37
29static const char * const default_event_names[] = { 38static const char * const default_event_names[] = {
30 [CM_EVENT_UNKNOWN] = "Unknown", 39 [CM_EVENT_UNKNOWN] = "Unknown",
31 [CM_EVENT_BATT_FULL] = "Battery Full", 40 [CM_EVENT_BATT_FULL] = "Battery Full",
32 [CM_EVENT_BATT_IN] = "Battery Inserted", 41 [CM_EVENT_BATT_IN] = "Battery Inserted",
33 [CM_EVENT_BATT_OUT] = "Battery Pulled Out", 42 [CM_EVENT_BATT_OUT] = "Battery Pulled Out",
43 [CM_EVENT_BATT_OVERHEAT] = "Battery Overheat",
44 [CM_EVENT_BATT_COLD] = "Battery Cold",
34 [CM_EVENT_EXT_PWR_IN_OUT] = "External Power Attach/Detach", 45 [CM_EVENT_EXT_PWR_IN_OUT] = "External Power Attach/Detach",
35 [CM_EVENT_CHG_START_STOP] = "Charging Start/Stop", 46 [CM_EVENT_CHG_START_STOP] = "Charging Start/Stop",
36 [CM_EVENT_OTHERS] = "Other battery events" 47 [CM_EVENT_OTHERS] = "Other battery events"
@@ -518,7 +529,7 @@ static int check_charging_duration(struct charger_manager *cm)
518 duration = curr - cm->charging_start_time; 529 duration = curr - cm->charging_start_time;
519 530
520 if (duration > desc->charging_max_duration_ms) { 531 if (duration > desc->charging_max_duration_ms) {
521 dev_info(cm->dev, "Charging duration exceed %lldms\n", 532 dev_info(cm->dev, "Charging duration exceed %ums\n",
522 desc->charging_max_duration_ms); 533 desc->charging_max_duration_ms);
523 uevent_notify(cm, "Discharging"); 534 uevent_notify(cm, "Discharging");
524 try_charger_enable(cm, false); 535 try_charger_enable(cm, false);
@@ -529,7 +540,7 @@ static int check_charging_duration(struct charger_manager *cm)
529 540
530 if (duration > desc->charging_max_duration_ms && 541 if (duration > desc->charging_max_duration_ms &&
531 is_ext_pwr_online(cm)) { 542 is_ext_pwr_online(cm)) {
532 dev_info(cm->dev, "Discharging duration exceed %lldms\n", 543 dev_info(cm->dev, "Discharging duration exceed %ums\n",
533 desc->discharging_max_duration_ms); 544 desc->discharging_max_duration_ms);
534 uevent_notify(cm, "Recharging"); 545 uevent_notify(cm, "Recharging");
535 try_charger_enable(cm, true); 546 try_charger_enable(cm, true);
@@ -540,6 +551,60 @@ static int check_charging_duration(struct charger_manager *cm)
540 return ret; 551 return ret;
541} 552}
542 553
554static int cm_get_battery_temperature(struct charger_manager *cm,
555 int *temp)
556{
557 int ret;
558
559 if (!cm->desc->measure_battery_temp)
560 return -ENODEV;
561
562#ifdef CONFIG_THERMAL
563 ret = thermal_zone_get_temp(cm->tzd_batt, (unsigned long *)temp);
564 if (!ret)
565 /* Calibrate temperature unit */
566 *temp /= 100;
567#else
568 ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
569 POWER_SUPPLY_PROP_TEMP,
570 (union power_supply_propval *)temp);
571#endif
572 return ret;
573}
574
575static int cm_check_thermal_status(struct charger_manager *cm)
576{
577 struct charger_desc *desc = cm->desc;
578 int temp, upper_limit, lower_limit;
579 int ret = 0;
580
581 ret = cm_get_battery_temperature(cm, &temp);
582 if (ret) {
583 /* FIXME:
584 * No information of battery temperature might
585 * occur hazadous result. We have to handle it
586 * depending on battery type.
587 */
588 dev_err(cm->dev, "Failed to get battery temperature\n");
589 return 0;
590 }
591
592 upper_limit = desc->temp_max;
593 lower_limit = desc->temp_min;
594
595 if (cm->emergency_stop) {
596 upper_limit -= desc->temp_diff;
597 lower_limit += desc->temp_diff;
598 }
599
600 if (temp > upper_limit)
601 ret = CM_EVENT_BATT_OVERHEAT;
602 else if (temp < lower_limit)
603 ret = CM_EVENT_BATT_COLD;
604
605 return ret;
606}
607
543/** 608/**
544 * _cm_monitor - Monitor the temperature and return true for exceptions. 609 * _cm_monitor - Monitor the temperature and return true for exceptions.
545 * @cm: the Charger Manager representing the battery. 610 * @cm: the Charger Manager representing the battery.
@@ -549,28 +614,22 @@ static int check_charging_duration(struct charger_manager *cm)
549 */ 614 */
550static bool _cm_monitor(struct charger_manager *cm) 615static bool _cm_monitor(struct charger_manager *cm)
551{ 616{
552 struct charger_desc *desc = cm->desc; 617 int temp_alrt;
553 int temp = desc->temperature_out_of_range(&cm->last_temp_mC);
554 618
555 dev_dbg(cm->dev, "monitoring (%2.2d.%3.3dC)\n", 619 temp_alrt = cm_check_thermal_status(cm);
556 cm->last_temp_mC / 1000, cm->last_temp_mC % 1000);
557 620
558 /* It has been stopped already */ 621 /* It has been stopped already */
559 if (temp && cm->emergency_stop) 622 if (temp_alrt && cm->emergency_stop)
560 return false; 623 return false;
561 624
562 /* 625 /*
563 * Check temperature whether overheat or cold. 626 * Check temperature whether overheat or cold.
564 * If temperature is out of range normal state, stop charging. 627 * If temperature is out of range normal state, stop charging.
565 */ 628 */
566 if (temp) { 629 if (temp_alrt) {
567 cm->emergency_stop = temp; 630 cm->emergency_stop = temp_alrt;
568 if (!try_charger_enable(cm, false)) { 631 if (!try_charger_enable(cm, false))
569 if (temp > 0) 632 uevent_notify(cm, default_event_names[temp_alrt]);
570 uevent_notify(cm, "OVERHEAT");
571 else
572 uevent_notify(cm, "COLD");
573 }
574 633
575 /* 634 /*
576 * Check whole charging duration and discharing duration 635 * Check whole charging duration and discharing duration
@@ -802,21 +861,8 @@ static int charger_get_property(struct power_supply *psy,
802 POWER_SUPPLY_PROP_CURRENT_NOW, val); 861 POWER_SUPPLY_PROP_CURRENT_NOW, val);
803 break; 862 break;
804 case POWER_SUPPLY_PROP_TEMP: 863 case POWER_SUPPLY_PROP_TEMP:
805 /* in thenth of centigrade */
806 if (cm->last_temp_mC == INT_MIN)
807 desc->temperature_out_of_range(&cm->last_temp_mC);
808 val->intval = cm->last_temp_mC / 100;
809 if (!desc->measure_battery_temp)
810 ret = -ENODEV;
811 break;
812 case POWER_SUPPLY_PROP_TEMP_AMBIENT: 864 case POWER_SUPPLY_PROP_TEMP_AMBIENT:
813 /* in thenth of centigrade */ 865 return cm_get_battery_temperature(cm, &val->intval);
814 if (cm->last_temp_mC == INT_MIN)
815 desc->temperature_out_of_range(&cm->last_temp_mC);
816 val->intval = cm->last_temp_mC / 100;
817 if (desc->measure_battery_temp)
818 ret = -ENODEV;
819 break;
820 case POWER_SUPPLY_PROP_CAPACITY: 866 case POWER_SUPPLY_PROP_CAPACITY:
821 if (!cm->fuel_gauge) { 867 if (!cm->fuel_gauge) {
822 ret = -ENODEV; 868 ret = -ENODEV;
@@ -1439,9 +1485,183 @@ err:
1439 return ret; 1485 return ret;
1440} 1486}
1441 1487
1488static int cm_init_thermal_data(struct charger_manager *cm)
1489{
1490 struct charger_desc *desc = cm->desc;
1491 union power_supply_propval val;
1492 int ret;
1493
1494 /* Verify whether fuel gauge provides battery temperature */
1495 ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
1496 POWER_SUPPLY_PROP_TEMP, &val);
1497
1498 if (!ret) {
1499 cm->charger_psy.properties[cm->charger_psy.num_properties] =
1500 POWER_SUPPLY_PROP_TEMP;
1501 cm->charger_psy.num_properties++;
1502 cm->desc->measure_battery_temp = true;
1503 }
1504#ifdef CONFIG_THERMAL
1505 cm->tzd_batt = cm->fuel_gauge->tzd;
1506
1507 if (ret && desc->thermal_zone) {
1508 cm->tzd_batt =
1509 thermal_zone_get_zone_by_name(desc->thermal_zone);
1510 if (IS_ERR(cm->tzd_batt))
1511 return PTR_ERR(cm->tzd_batt);
1512
1513 /* Use external thermometer */
1514 cm->charger_psy.properties[cm->charger_psy.num_properties] =
1515 POWER_SUPPLY_PROP_TEMP_AMBIENT;
1516 cm->charger_psy.num_properties++;
1517 cm->desc->measure_battery_temp = true;
1518 ret = 0;
1519 }
1520#endif
1521 if (cm->desc->measure_battery_temp) {
1522 /* NOTICE : Default allowable minimum charge temperature is 0 */
1523 if (!desc->temp_max)
1524 desc->temp_max = CM_DEFAULT_CHARGE_TEMP_MAX;
1525 if (!desc->temp_diff)
1526 desc->temp_diff = CM_DEFAULT_RECHARGE_TEMP_DIFF;
1527 }
1528
1529 return ret;
1530}
1531
1532static struct of_device_id charger_manager_match[] = {
1533 {
1534 .compatible = "charger-manager",
1535 },
1536 {},
1537};
1538
1539static struct charger_desc *of_cm_parse_desc(struct device *dev)
1540{
1541 struct charger_desc *desc;
1542 struct device_node *np = dev->of_node;
1543 u32 poll_mode = CM_POLL_DISABLE;
1544 u32 battery_stat = CM_NO_BATTERY;
1545 int num_chgs = 0;
1546
1547 desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
1548 if (!desc)
1549 return ERR_PTR(-ENOMEM);
1550
1551 of_property_read_string(np, "cm-name", &desc->psy_name);
1552
1553 of_property_read_u32(np, "cm-poll-mode", &poll_mode);
1554 desc->polling_mode = poll_mode;
1555
1556 of_property_read_u32(np, "cm-poll-interval",
1557 &desc->polling_interval_ms);
1558
1559 of_property_read_u32(np, "cm-fullbatt-vchkdrop-ms",
1560 &desc->fullbatt_vchkdrop_ms);
1561 of_property_read_u32(np, "cm-fullbatt-vchkdrop-volt",
1562 &desc->fullbatt_vchkdrop_uV);
1563 of_property_read_u32(np, "cm-fullbatt-voltage", &desc->fullbatt_uV);
1564 of_property_read_u32(np, "cm-fullbatt-soc", &desc->fullbatt_soc);
1565 of_property_read_u32(np, "cm-fullbatt-capacity",
1566 &desc->fullbatt_full_capacity);
1567
1568 of_property_read_u32(np, "cm-battery-stat", &battery_stat);
1569 desc->battery_present = battery_stat;
1570
1571 /* chargers */
1572 of_property_read_u32(np, "cm-num-chargers", &num_chgs);
1573 if (num_chgs) {
1574 /* Allocate empty bin at the tail of array */
1575 desc->psy_charger_stat = devm_kzalloc(dev, sizeof(char *)
1576 * (num_chgs + 1), GFP_KERNEL);
1577 if (desc->psy_charger_stat) {
1578 int i;
1579 for (i = 0; i < num_chgs; i++)
1580 of_property_read_string_index(np, "cm-chargers",
1581 i, &desc->psy_charger_stat[i]);
1582 } else {
1583 return ERR_PTR(-ENOMEM);
1584 }
1585 }
1586
1587 of_property_read_string(np, "cm-fuel-gauge", &desc->psy_fuel_gauge);
1588
1589 of_property_read_string(np, "cm-thermal-zone", &desc->thermal_zone);
1590
1591 of_property_read_u32(np, "cm-battery-cold", &desc->temp_min);
1592 if (of_get_property(np, "cm-battery-cold-in-minus", NULL))
1593 desc->temp_min *= -1;
1594 of_property_read_u32(np, "cm-battery-hot", &desc->temp_max);
1595 of_property_read_u32(np, "cm-battery-temp-diff", &desc->temp_diff);
1596
1597 of_property_read_u32(np, "cm-charging-max",
1598 &desc->charging_max_duration_ms);
1599 of_property_read_u32(np, "cm-discharging-max",
1600 &desc->discharging_max_duration_ms);
1601
1602 /* battery charger regualtors */
1603 desc->num_charger_regulators = of_get_child_count(np);
1604 if (desc->num_charger_regulators) {
1605 struct charger_regulator *chg_regs;
1606 struct device_node *child;
1607
1608 chg_regs = devm_kzalloc(dev, sizeof(*chg_regs)
1609 * desc->num_charger_regulators,
1610 GFP_KERNEL);
1611 if (!chg_regs)
1612 return ERR_PTR(-ENOMEM);
1613
1614 desc->charger_regulators = chg_regs;
1615
1616 for_each_child_of_node(np, child) {
1617 struct charger_cable *cables;
1618 struct device_node *_child;
1619
1620 of_property_read_string(child, "cm-regulator-name",
1621 &chg_regs->regulator_name);
1622
1623 /* charger cables */
1624 chg_regs->num_cables = of_get_child_count(child);
1625 if (chg_regs->num_cables) {
1626 cables = devm_kzalloc(dev, sizeof(*cables)
1627 * chg_regs->num_cables,
1628 GFP_KERNEL);
1629 if (!cables)
1630 return ERR_PTR(-ENOMEM);
1631
1632 chg_regs->cables = cables;
1633
1634 for_each_child_of_node(child, _child) {
1635 of_property_read_string(_child,
1636 "cm-cable-name", &cables->name);
1637 of_property_read_string(_child,
1638 "cm-cable-extcon",
1639 &cables->extcon_name);
1640 of_property_read_u32(_child,
1641 "cm-cable-min",
1642 &cables->min_uA);
1643 of_property_read_u32(_child,
1644 "cm-cable-max",
1645 &cables->max_uA);
1646 cables++;
1647 }
1648 }
1649 chg_regs++;
1650 }
1651 }
1652 return desc;
1653}
1654
1655static inline struct charger_desc *cm_get_drv_data(struct platform_device *pdev)
1656{
1657 if (pdev->dev.of_node)
1658 return of_cm_parse_desc(&pdev->dev);
1659 return (struct charger_desc *)dev_get_platdata(&pdev->dev);
1660}
1661
1442static int charger_manager_probe(struct platform_device *pdev) 1662static int charger_manager_probe(struct platform_device *pdev)
1443{ 1663{
1444 struct charger_desc *desc = dev_get_platdata(&pdev->dev); 1664 struct charger_desc *desc = cm_get_drv_data(pdev);
1445 struct charger_manager *cm; 1665 struct charger_manager *cm;
1446 int ret = 0, i = 0; 1666 int ret = 0, i = 0;
1447 int j = 0; 1667 int j = 0;
@@ -1470,7 +1690,6 @@ static int charger_manager_probe(struct platform_device *pdev)
1470 /* Basic Values. Unspecified are Null or 0 */ 1690 /* Basic Values. Unspecified are Null or 0 */
1471 cm->dev = &pdev->dev; 1691 cm->dev = &pdev->dev;
1472 cm->desc = desc; 1692 cm->desc = desc;
1473 cm->last_temp_mC = INT_MIN; /* denotes "unmeasured, yet" */
1474 1693
1475 /* 1694 /*
1476 * The following two do not need to be errors. 1695 * The following two do not need to be errors.
@@ -1533,11 +1752,6 @@ static int charger_manager_probe(struct platform_device *pdev)
1533 return -EINVAL; 1752 return -EINVAL;
1534 } 1753 }
1535 1754
1536 if (!desc->temperature_out_of_range) {
1537 dev_err(&pdev->dev, "there is no temperature_out_of_range\n");
1538 return -EINVAL;
1539 }
1540
1541 if (!desc->charging_max_duration_ms || 1755 if (!desc->charging_max_duration_ms ||
1542 !desc->discharging_max_duration_ms) { 1756 !desc->discharging_max_duration_ms) {
1543 dev_info(&pdev->dev, "Cannot limit charging duration checking mechanism to prevent overcharge/overheat and control discharging duration\n"); 1757 dev_info(&pdev->dev, "Cannot limit charging duration checking mechanism to prevent overcharge/overheat and control discharging duration\n");
@@ -1583,14 +1797,10 @@ static int charger_manager_probe(struct platform_device *pdev)
1583 cm->charger_psy.num_properties++; 1797 cm->charger_psy.num_properties++;
1584 } 1798 }
1585 1799
1586 if (desc->measure_battery_temp) { 1800 ret = cm_init_thermal_data(cm);
1587 cm->charger_psy.properties[cm->charger_psy.num_properties] = 1801 if (ret) {
1588 POWER_SUPPLY_PROP_TEMP; 1802 dev_err(&pdev->dev, "Failed to initialize thermal data\n");
1589 cm->charger_psy.num_properties++; 1803 cm->desc->measure_battery_temp = false;
1590 } else {
1591 cm->charger_psy.properties[cm->charger_psy.num_properties] =
1592 POWER_SUPPLY_PROP_TEMP_AMBIENT;
1593 cm->charger_psy.num_properties++;
1594 } 1804 }
1595 1805
1596 INIT_DELAYED_WORK(&cm->fullbatt_vchk_work, fullbatt_vchk); 1806 INIT_DELAYED_WORK(&cm->fullbatt_vchk_work, fullbatt_vchk);
@@ -1808,6 +2018,7 @@ static struct platform_driver charger_manager_driver = {
1808 .name = "charger-manager", 2018 .name = "charger-manager",
1809 .owner = THIS_MODULE, 2019 .owner = THIS_MODULE,
1810 .pm = &charger_manager_pm, 2020 .pm = &charger_manager_pm,
2021 .of_match_table = charger_manager_match,
1811 }, 2022 },
1812 .probe = charger_manager_probe, 2023 .probe = charger_manager_probe,
1813 .remove = charger_manager_remove, 2024 .remove = charger_manager_remove,
diff --git a/drivers/power/gpio-charger.c b/drivers/power/gpio-charger.c
index 4e858a23568f..a0024b252197 100644
--- a/drivers/power/gpio-charger.c
+++ b/drivers/power/gpio-charger.c
@@ -28,6 +28,7 @@
28struct gpio_charger { 28struct gpio_charger {
29 const struct gpio_charger_platform_data *pdata; 29 const struct gpio_charger_platform_data *pdata;
30 unsigned int irq; 30 unsigned int irq;
31 bool wakeup_enabled;
31 32
32 struct power_supply charger; 33 struct power_supply charger;
33}; 34};
@@ -136,6 +137,8 @@ static int gpio_charger_probe(struct platform_device *pdev)
136 137
137 platform_set_drvdata(pdev, gpio_charger); 138 platform_set_drvdata(pdev, gpio_charger);
138 139
140 device_init_wakeup(&pdev->dev, 1);
141
139 return 0; 142 return 0;
140 143
141err_gpio_free: 144err_gpio_free:
@@ -159,18 +162,32 @@ static int gpio_charger_remove(struct platform_device *pdev)
159} 162}
160 163
161#ifdef CONFIG_PM_SLEEP 164#ifdef CONFIG_PM_SLEEP
165static int gpio_charger_suspend(struct device *dev)
166{
167 struct gpio_charger *gpio_charger = dev_get_drvdata(dev);
168
169 if (device_may_wakeup(dev))
170 gpio_charger->wakeup_enabled =
171 enable_irq_wake(gpio_charger->irq);
172
173 return 0;
174}
175
162static int gpio_charger_resume(struct device *dev) 176static int gpio_charger_resume(struct device *dev)
163{ 177{
164 struct platform_device *pdev = to_platform_device(dev); 178 struct platform_device *pdev = to_platform_device(dev);
165 struct gpio_charger *gpio_charger = platform_get_drvdata(pdev); 179 struct gpio_charger *gpio_charger = platform_get_drvdata(pdev);
166 180
181 if (gpio_charger->wakeup_enabled)
182 disable_irq_wake(gpio_charger->irq);
167 power_supply_changed(&gpio_charger->charger); 183 power_supply_changed(&gpio_charger->charger);
168 184
169 return 0; 185 return 0;
170} 186}
171#endif 187#endif
172 188
173static SIMPLE_DEV_PM_OPS(gpio_charger_pm_ops, NULL, gpio_charger_resume); 189static SIMPLE_DEV_PM_OPS(gpio_charger_pm_ops,
190 gpio_charger_suspend, gpio_charger_resume);
174 191
175static struct platform_driver gpio_charger_driver = { 192static struct platform_driver gpio_charger_driver = {
176 .probe = gpio_charger_probe, 193 .probe = gpio_charger_probe,
diff --git a/drivers/power/isp1704_charger.c b/drivers/power/isp1704_charger.c
index 1bb3a91b1acc..80edb7d8cb54 100644
--- a/drivers/power/isp1704_charger.c
+++ b/drivers/power/isp1704_charger.c
@@ -29,6 +29,8 @@
29#include <linux/platform_device.h> 29#include <linux/platform_device.h>
30#include <linux/power_supply.h> 30#include <linux/power_supply.h>
31#include <linux/delay.h> 31#include <linux/delay.h>
32#include <linux/of.h>
33#include <linux/of_gpio.h>
32 34
33#include <linux/usb/otg.h> 35#include <linux/usb/otg.h>
34#include <linux/usb/ulpi.h> 36#include <linux/usb/ulpi.h>
@@ -88,6 +90,8 @@ static void isp1704_charger_set_power(struct isp1704_charger *isp, bool on)
88 90
89 if (board && board->set_power) 91 if (board && board->set_power)
90 board->set_power(on); 92 board->set_power(on);
93 else if (board)
94 gpio_set_value(board->enable_gpio, on);
91} 95}
92 96
93/* 97/*
@@ -400,12 +404,47 @@ static int isp1704_charger_probe(struct platform_device *pdev)
400 struct isp1704_charger *isp; 404 struct isp1704_charger *isp;
401 int ret = -ENODEV; 405 int ret = -ENODEV;
402 406
407 struct isp1704_charger_data *pdata = dev_get_platdata(&pdev->dev);
408 struct device_node *np = pdev->dev.of_node;
409
410 if (np) {
411 int gpio = of_get_named_gpio(np, "nxp,enable-gpio", 0);
412
413 if (gpio < 0)
414 return gpio;
415
416 pdata = devm_kzalloc(&pdev->dev,
417 sizeof(struct isp1704_charger_data), GFP_KERNEL);
418 pdata->enable_gpio = gpio;
419
420 dev_info(&pdev->dev, "init gpio %d\n", pdata->enable_gpio);
421
422 ret = devm_gpio_request_one(&pdev->dev, pdata->enable_gpio,
423 GPIOF_OUT_INIT_HIGH, "isp1704_reset");
424 if (ret)
425 goto fail0;
426 }
427
428 if (!pdata) {
429 dev_err(&pdev->dev, "missing platform data!\n");
430 return -ENODEV;
431 }
432
433
403 isp = devm_kzalloc(&pdev->dev, sizeof(*isp), GFP_KERNEL); 434 isp = devm_kzalloc(&pdev->dev, sizeof(*isp), GFP_KERNEL);
404 if (!isp) 435 if (!isp)
405 return -ENOMEM; 436 return -ENOMEM;
406 437
407 isp->phy = usb_get_phy(USB_PHY_TYPE_USB2); 438 if (np)
408 if (IS_ERR_OR_NULL(isp->phy)) 439 isp->phy = devm_usb_get_phy_by_phandle(&pdev->dev, "usb-phy", 0);
440 else
441 isp->phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
442
443 if (IS_ERR(isp->phy)) {
444 ret = PTR_ERR(isp->phy);
445 goto fail0;
446 }
447 if (!isp->phy)
409 goto fail0; 448 goto fail0;
410 449
411 isp->dev = &pdev->dev; 450 isp->dev = &pdev->dev;
@@ -464,7 +503,6 @@ fail2:
464 power_supply_unregister(&isp->psy); 503 power_supply_unregister(&isp->psy);
465fail1: 504fail1:
466 isp1704_charger_set_power(isp, 0); 505 isp1704_charger_set_power(isp, 0);
467 usb_put_phy(isp->phy);
468fail0: 506fail0:
469 dev_err(&pdev->dev, "failed to register isp1704 with error %d\n", ret); 507 dev_err(&pdev->dev, "failed to register isp1704 with error %d\n", ret);
470 508
@@ -477,15 +515,23 @@ static int isp1704_charger_remove(struct platform_device *pdev)
477 515
478 usb_unregister_notifier(isp->phy, &isp->nb); 516 usb_unregister_notifier(isp->phy, &isp->nb);
479 power_supply_unregister(&isp->psy); 517 power_supply_unregister(&isp->psy);
480 usb_put_phy(isp->phy);
481 isp1704_charger_set_power(isp, 0); 518 isp1704_charger_set_power(isp, 0);
482 519
483 return 0; 520 return 0;
484} 521}
485 522
523#ifdef CONFIG_OF
524static const struct of_device_id omap_isp1704_of_match[] = {
525 { .compatible = "nxp,isp1704", },
526 {},
527};
528MODULE_DEVICE_TABLE(of, omap_isp1704_of_match);
529#endif
530
486static struct platform_driver isp1704_charger_driver = { 531static struct platform_driver isp1704_charger_driver = {
487 .driver = { 532 .driver = {
488 .name = "isp1704_charger", 533 .name = "isp1704_charger",
534 .of_match_table = of_match_ptr(omap_isp1704_of_match),
489 }, 535 },
490 .probe = isp1704_charger_probe, 536 .probe = isp1704_charger_probe,
491 .remove = isp1704_charger_remove, 537 .remove = isp1704_charger_remove,
diff --git a/drivers/power/max14577_charger.c b/drivers/power/max14577_charger.c
new file mode 100644
index 000000000000..fad2a75b3604
--- /dev/null
+++ b/drivers/power/max14577_charger.c
@@ -0,0 +1,311 @@
1/*
2 * Battery charger driver for the Maxim 14577
3 *
4 * Copyright (C) 2013 Samsung Electronics
5 * Krzysztof Kozlowski <k.kozlowski@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#include <linux/module.h>
19#include <linux/platform_device.h>
20#include <linux/power_supply.h>
21#include <linux/mfd/max14577-private.h>
22
23struct max14577_charger {
24 struct device *dev;
25 struct max14577 *max14577;
26 struct power_supply charger;
27
28 unsigned int charging_state;
29 unsigned int battery_state;
30};
31
32static int max14577_get_charger_state(struct max14577_charger *chg)
33{
34 struct regmap *rmap = chg->max14577->regmap;
35 int state = POWER_SUPPLY_STATUS_DISCHARGING;
36 u8 reg_data;
37
38 /*
39 * Charging occurs only if:
40 * - CHGCTRL2/MBCHOSTEN == 1
41 * - STATUS2/CGMBC == 1
42 *
43 * TODO:
44 * - handle FULL after Top-off timer (EOC register may be off
45 * and the charger won't be charging although MBCHOSTEN is on)
46 * - handle properly dead-battery charging (respect timer)
47 * - handle timers (fast-charge and prequal) /MBCCHGERR/
48 */
49 max14577_read_reg(rmap, MAX14577_CHG_REG_CHG_CTRL2, &reg_data);
50 if ((reg_data & CHGCTRL2_MBCHOSTEN_MASK) == 0)
51 goto state_set;
52
53 max14577_read_reg(rmap, MAX14577_CHG_REG_STATUS3, &reg_data);
54 if (reg_data & STATUS3_CGMBC_MASK) {
55 /* Charger or USB-cable is connected */
56 if (reg_data & STATUS3_EOC_MASK)
57 state = POWER_SUPPLY_STATUS_FULL;
58 else
59 state = POWER_SUPPLY_STATUS_CHARGING;
60 goto state_set;
61 }
62
63state_set:
64 chg->charging_state = state;
65 return state;
66}
67
68/*
69 * Supported charge types:
70 * - POWER_SUPPLY_CHARGE_TYPE_NONE
71 * - POWER_SUPPLY_CHARGE_TYPE_FAST
72 */
73static int max14577_get_charge_type(struct max14577_charger *chg)
74{
75 /*
76 * TODO: CHARGE_TYPE_TRICKLE (VCHGR_RC or EOC)?
77 * As spec says:
78 * [after reaching EOC interrupt]
79 * "When the battery is fully charged, the 30-minute (typ)
80 * top-off timer starts. The device continues to trickle
81 * charge the battery until the top-off timer runs out."
82 */
83 if (max14577_get_charger_state(chg) == POWER_SUPPLY_STATUS_CHARGING)
84 return POWER_SUPPLY_CHARGE_TYPE_FAST;
85 return POWER_SUPPLY_CHARGE_TYPE_NONE;
86}
87
88static int max14577_get_online(struct max14577_charger *chg)
89{
90 struct regmap *rmap = chg->max14577->regmap;
91 u8 reg_data;
92
93 max14577_read_reg(rmap, MAX14577_MUIC_REG_STATUS2, &reg_data);
94 reg_data = ((reg_data & STATUS2_CHGTYP_MASK) >> STATUS2_CHGTYP_SHIFT);
95 switch (reg_data) {
96 case MAX14577_CHARGER_TYPE_USB:
97 case MAX14577_CHARGER_TYPE_DEDICATED_CHG:
98 case MAX14577_CHARGER_TYPE_SPECIAL_500MA:
99 case MAX14577_CHARGER_TYPE_SPECIAL_1A:
100 case MAX14577_CHARGER_TYPE_DEAD_BATTERY:
101 return 1;
102 case MAX14577_CHARGER_TYPE_NONE:
103 case MAX14577_CHARGER_TYPE_DOWNSTREAM_PORT:
104 case MAX14577_CHARGER_TYPE_RESERVED:
105 default:
106 return 0;
107 }
108}
109
110/*
111 * Supported health statuses:
112 * - POWER_SUPPLY_HEALTH_DEAD
113 * - POWER_SUPPLY_HEALTH_OVERVOLTAGE
114 * - POWER_SUPPLY_HEALTH_GOOD
115 */
116static int max14577_get_battery_health(struct max14577_charger *chg)
117{
118 struct regmap *rmap = chg->max14577->regmap;
119 int state = POWER_SUPPLY_HEALTH_GOOD;
120 u8 reg_data;
121
122 max14577_read_reg(rmap, MAX14577_MUIC_REG_STATUS2, &reg_data);
123 reg_data = ((reg_data & STATUS2_CHGTYP_MASK) >> STATUS2_CHGTYP_SHIFT);
124 if (reg_data == MAX14577_CHARGER_TYPE_DEAD_BATTERY) {
125 state = POWER_SUPPLY_HEALTH_DEAD;
126 goto state_set;
127 }
128
129 max14577_read_reg(rmap, MAX14577_CHG_REG_STATUS3, &reg_data);
130 if (reg_data & STATUS3_OVP_MASK) {
131 state = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
132 goto state_set;
133 }
134
135state_set:
136 chg->battery_state = state;
137 return state;
138}
139
140/*
141 * Always returns 1.
142 * The max14577 chip doesn't report any status of battery presence.
143 * Lets assume that it will always be used with some battery.
144 */
145static int max14577_get_present(struct max14577_charger *chg)
146{
147 return 1;
148}
149
150/*
151 * Sets charger registers to proper and safe default values.
152 * Some of these values are equal to defaults in MAX14577E
153 * data sheet but there are minor differences.
154 */
155static void max14577_charger_reg_init(struct max14577_charger *chg)
156{
157 struct regmap *rmap = chg->max14577->regmap;
158 u8 reg_data;
159
160 /*
161 * Charger-Type Manual Detection, default off (set CHGTYPMAN to 0)
162 * Charger-Detection Enable, default on (set CHGDETEN to 1)
163 * Combined mask of CHGDETEN and CHGTYPMAN will zero the CHGTYPMAN bit
164 */
165 reg_data = 0x1 << CDETCTRL1_CHGDETEN_SHIFT;
166 max14577_update_reg(rmap, MAX14577_REG_CDETCTRL1,
167 CDETCTRL1_CHGDETEN_MASK | CDETCTRL1_CHGTYPMAN_MASK,
168 reg_data);
169
170 /* Battery Fast-Charge Timer, from SM-V700: 6hrs */
171 reg_data = 0x3 << CHGCTRL1_TCHW_SHIFT;
172 max14577_write_reg(rmap, MAX14577_REG_CHGCTRL1, reg_data);
173
174 /*
175 * Wall-Adapter Rapid Charge, default on
176 * Battery-Charger, default on
177 */
178 reg_data = 0x1 << CHGCTRL2_VCHGR_RC_SHIFT;
179 reg_data |= 0x1 << CHGCTRL2_MBCHOSTEN_SHIFT;
180 max14577_write_reg(rmap, MAX14577_REG_CHGCTRL2, reg_data);
181
182 /* Battery-Charger Constant Voltage (CV) Mode, from SM-V700: 4.35V */
183 reg_data = 0xf << CHGCTRL3_MBCCVWRC_SHIFT;
184 max14577_write_reg(rmap, MAX14577_REG_CHGCTRL3, reg_data);
185
186 /*
187 * Fast Battery-Charge Current Low, default 200-950mA
188 * Fast Battery-Charge Current High, from SM-V700: 450mA
189 */
190 reg_data = 0x1 << CHGCTRL4_MBCICHWRCL_SHIFT;
191 reg_data |= 0x5 << CHGCTRL4_MBCICHWRCH_SHIFT;
192 max14577_write_reg(rmap, MAX14577_REG_CHGCTRL4, reg_data);
193
194 /* End-of-Charge Current, from SM-V700: 50mA */
195 reg_data = 0x0 << CHGCTRL5_EOCS_SHIFT;
196 max14577_write_reg(rmap, MAX14577_REG_CHGCTRL5, reg_data);
197
198 /* Auto Charging Stop, default off */
199 reg_data = 0x0 << CHGCTRL6_AUTOSTOP_SHIFT;
200 max14577_write_reg(rmap, MAX14577_REG_CHGCTRL6, reg_data);
201
202 /* Overvoltage-Protection Threshold, from SM-V700: 6.5V */
203 reg_data = 0x2 << CHGCTRL7_OTPCGHCVS_SHIFT;
204 max14577_write_reg(rmap, MAX14577_REG_CHGCTRL7, reg_data);
205}
206
207/* Support property from charger */
208static enum power_supply_property max14577_charger_props[] = {
209 POWER_SUPPLY_PROP_STATUS,
210 POWER_SUPPLY_PROP_CHARGE_TYPE,
211 POWER_SUPPLY_PROP_HEALTH,
212 POWER_SUPPLY_PROP_PRESENT,
213 POWER_SUPPLY_PROP_ONLINE,
214 POWER_SUPPLY_PROP_MODEL_NAME,
215 POWER_SUPPLY_PROP_MANUFACTURER,
216};
217
218static const char *model_name = "MAX14577";
219static const char *manufacturer = "Maxim Integrated";
220
221static int max14577_charger_get_property(struct power_supply *psy,
222 enum power_supply_property psp,
223 union power_supply_propval *val)
224{
225 struct max14577_charger *chg = container_of(psy,
226 struct max14577_charger,
227 charger);
228 int ret = 0;
229
230 switch (psp) {
231 case POWER_SUPPLY_PROP_STATUS:
232 val->intval = max14577_get_charger_state(chg);
233 break;
234 case POWER_SUPPLY_PROP_CHARGE_TYPE:
235 val->intval = max14577_get_charge_type(chg);
236 break;
237 case POWER_SUPPLY_PROP_HEALTH:
238 val->intval = max14577_get_battery_health(chg);
239 break;
240 case POWER_SUPPLY_PROP_PRESENT:
241 val->intval = max14577_get_present(chg);
242 break;
243 case POWER_SUPPLY_PROP_ONLINE:
244 val->intval = max14577_get_online(chg);
245 break;
246 case POWER_SUPPLY_PROP_MODEL_NAME:
247 val->strval = model_name;
248 break;
249 case POWER_SUPPLY_PROP_MANUFACTURER:
250 val->strval = manufacturer;
251 break;
252 default:
253 return -EINVAL;
254 }
255
256 return ret;
257}
258
259static int max14577_charger_probe(struct platform_device *pdev)
260{
261 struct max14577_charger *chg;
262 struct max14577 *max14577 = dev_get_drvdata(pdev->dev.parent);
263 int ret;
264
265 chg = devm_kzalloc(&pdev->dev, sizeof(*chg), GFP_KERNEL);
266 if (!chg)
267 return -ENOMEM;
268
269 platform_set_drvdata(pdev, chg);
270 chg->dev = &pdev->dev;
271 chg->max14577 = max14577;
272
273 max14577_charger_reg_init(chg);
274
275 chg->charger.name = "max14577-charger",
276 chg->charger.type = POWER_SUPPLY_TYPE_BATTERY,
277 chg->charger.properties = max14577_charger_props,
278 chg->charger.num_properties = ARRAY_SIZE(max14577_charger_props),
279 chg->charger.get_property = max14577_charger_get_property,
280
281 ret = power_supply_register(&pdev->dev, &chg->charger);
282 if (ret) {
283 dev_err(&pdev->dev, "failed: power supply register\n");
284 return ret;
285 }
286
287 return 0;
288}
289
290static int max14577_charger_remove(struct platform_device *pdev)
291{
292 struct max14577_charger *chg = platform_get_drvdata(pdev);
293
294 power_supply_unregister(&chg->charger);
295
296 return 0;
297}
298
299static struct platform_driver max14577_charger_driver = {
300 .driver = {
301 .owner = THIS_MODULE,
302 .name = "max14577-charger",
303 },
304 .probe = max14577_charger_probe,
305 .remove = max14577_charger_remove,
306};
307module_platform_driver(max14577_charger_driver);
308
309MODULE_AUTHOR("Krzysztof Kozlowski <k.kozlowski@samsung.com>");
310MODULE_DESCRIPTION("MAXIM 14577 charger driver");
311MODULE_LICENSE("GPL");
diff --git a/drivers/power/max17042_battery.c b/drivers/power/max17042_battery.c
index e0b22f9b6fdd..66da691c41cf 100644
--- a/drivers/power/max17042_battery.c
+++ b/drivers/power/max17042_battery.c
@@ -741,9 +741,9 @@ static int max17042_probe(struct i2c_client *client,
741 741
742 if (client->irq) { 742 if (client->irq) {
743 ret = request_threaded_irq(client->irq, NULL, 743 ret = request_threaded_irq(client->irq, NULL,
744 max17042_thread_handler, 744 max17042_thread_handler,
745 IRQF_TRIGGER_FALLING, 745 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
746 chip->battery.name, chip); 746 chip->battery.name, chip);
747 if (!ret) { 747 if (!ret) {
748 regmap_read(chip->regmap, MAX17042_CONFIG, &val); 748 regmap_read(chip->regmap, MAX17042_CONFIG, &val);
749 val |= CONFIG_ALRT_BIT_ENBL; 749 val |= CONFIG_ALRT_BIT_ENBL;
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index 557af943b2f5..26606641fe44 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -15,6 +15,7 @@
15#include <linux/init.h> 15#include <linux/init.h>
16#include <linux/slab.h> 16#include <linux/slab.h>
17#include <linux/device.h> 17#include <linux/device.h>
18#include <linux/notifier.h>
18#include <linux/err.h> 19#include <linux/err.h>
19#include <linux/power_supply.h> 20#include <linux/power_supply.h>
20#include <linux/thermal.h> 21#include <linux/thermal.h>
@@ -24,6 +25,9 @@
24struct class *power_supply_class; 25struct class *power_supply_class;
25EXPORT_SYMBOL_GPL(power_supply_class); 26EXPORT_SYMBOL_GPL(power_supply_class);
26 27
28ATOMIC_NOTIFIER_HEAD(power_supply_notifier);
29EXPORT_SYMBOL_GPL(power_supply_notifier);
30
27static struct device_type power_supply_dev_type; 31static struct device_type power_supply_dev_type;
28 32
29static bool __power_supply_is_supplied_by(struct power_supply *supplier, 33static bool __power_supply_is_supplied_by(struct power_supply *supplier,
@@ -80,6 +84,8 @@ static void power_supply_changed_work(struct work_struct *work)
80 class_for_each_device(power_supply_class, NULL, psy, 84 class_for_each_device(power_supply_class, NULL, psy,
81 __power_supply_changed_work); 85 __power_supply_changed_work);
82 power_supply_update_leds(psy); 86 power_supply_update_leds(psy);
87 atomic_notifier_call_chain(&power_supply_notifier,
88 PSY_EVENT_PROP_CHANGED, psy);
83 kobject_uevent(&psy->dev->kobj, KOBJ_CHANGE); 89 kobject_uevent(&psy->dev->kobj, KOBJ_CHANGE);
84 spin_lock_irqsave(&psy->changed_lock, flags); 90 spin_lock_irqsave(&psy->changed_lock, flags);
85 } 91 }
@@ -335,6 +341,32 @@ struct power_supply *power_supply_get_by_name(const char *name)
335} 341}
336EXPORT_SYMBOL_GPL(power_supply_get_by_name); 342EXPORT_SYMBOL_GPL(power_supply_get_by_name);
337 343
344#ifdef CONFIG_OF
345static int power_supply_match_device_node(struct device *dev, const void *data)
346{
347 return dev->parent && dev->parent->of_node == data;
348}
349
350struct power_supply *power_supply_get_by_phandle(struct device_node *np,
351 const char *property)
352{
353 struct device_node *power_supply_np;
354 struct device *dev;
355
356 power_supply_np = of_parse_phandle(np, property, 0);
357 if (!power_supply_np)
358 return ERR_PTR(-ENODEV);
359
360 dev = class_find_device(power_supply_class, NULL, power_supply_np,
361 power_supply_match_device_node);
362
363 of_node_put(power_supply_np);
364
365 return dev ? dev_get_drvdata(dev) : NULL;
366}
367EXPORT_SYMBOL_GPL(power_supply_get_by_phandle);
368#endif /* CONFIG_OF */
369
338int power_supply_powers(struct power_supply *psy, struct device *dev) 370int power_supply_powers(struct power_supply *psy, struct device *dev)
339{ 371{
340 return sysfs_create_link(&psy->dev->kobj, &dev->kobj, "powers"); 372 return sysfs_create_link(&psy->dev->kobj, &dev->kobj, "powers");
@@ -347,6 +379,18 @@ static void power_supply_dev_release(struct device *dev)
347 kfree(dev); 379 kfree(dev);
348} 380}
349 381
382int power_supply_reg_notifier(struct notifier_block *nb)
383{
384 return atomic_notifier_chain_register(&power_supply_notifier, nb);
385}
386EXPORT_SYMBOL_GPL(power_supply_reg_notifier);
387
388void power_supply_unreg_notifier(struct notifier_block *nb)
389{
390 atomic_notifier_chain_unregister(&power_supply_notifier, nb);
391}
392EXPORT_SYMBOL_GPL(power_supply_unreg_notifier);
393
350#ifdef CONFIG_THERMAL 394#ifdef CONFIG_THERMAL
351static int power_supply_read_temp(struct thermal_zone_device *tzd, 395static int power_supply_read_temp(struct thermal_zone_device *tzd,
352 unsigned long *temp) 396 unsigned long *temp)
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index 9b3ea535b472..6d452a78b19c 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -6,6 +6,12 @@ menuconfig POWER_RESET
6 6
7 Say Y here to enable board reset and power off 7 Say Y here to enable board reset and power off
8 8
9config POWER_RESET_AS3722
10 bool "ams AS3722 power-off driver"
11 depends on MFD_AS3722 && POWER_RESET
12 help
13 This driver supports turning off board via a ams AS3722 power-off.
14
9config POWER_RESET_GPIO 15config POWER_RESET_GPIO
10 bool "GPIO power-off driver" 16 bool "GPIO power-off driver"
11 depends on OF_GPIO && POWER_RESET 17 depends on OF_GPIO && POWER_RESET
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index 3e6ed88725ac..a5b4a77d1a41 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -1,3 +1,4 @@
1obj-$(CONFIG_POWER_RESET_AS3722) += as3722-poweroff.o
1obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o 2obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
2obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o 3obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o
3obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o 4obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o
diff --git a/drivers/power/reset/as3722-poweroff.c b/drivers/power/reset/as3722-poweroff.c
new file mode 100644
index 000000000000..684971199bd3
--- /dev/null
+++ b/drivers/power/reset/as3722-poweroff.c
@@ -0,0 +1,96 @@
1/*
2 * Power off driver for ams AS3722 device.
3 *
4 * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
5 *
6 * Author: Laxman Dewangan <ldewangan@nvidia.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2, as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 */
17
18#include <linux/mfd/as3722.h>
19#include <linux/module.h>
20#include <linux/of.h>
21#include <linux/of_device.h>
22#include <linux/platform_device.h>
23#include <linux/slab.h>
24
25struct as3722_poweroff {
26 struct device *dev;
27 struct as3722 *as3722;
28};
29
30static struct as3722_poweroff *as3722_pm_poweroff;
31
32static void as3722_pm_power_off(void)
33{
34 int ret;
35
36 if (!as3722_pm_poweroff) {
37 pr_err("AS3722 poweroff is not initialised\n");
38 return;
39 }
40
41 ret = as3722_update_bits(as3722_pm_poweroff->as3722,
42 AS3722_RESET_CONTROL_REG, AS3722_POWER_OFF, AS3722_POWER_OFF);
43 if (ret < 0)
44 dev_err(as3722_pm_poweroff->dev,
45 "RESET_CONTROL_REG update failed, %d\n", ret);
46}
47
48static int as3722_poweroff_probe(struct platform_device *pdev)
49{
50 struct as3722_poweroff *as3722_poweroff;
51 struct device_node *np = pdev->dev.parent->of_node;
52
53 if (!np)
54 return -EINVAL;
55
56 if (!of_property_read_bool(np, "ams,system-power-controller"))
57 return 0;
58
59 as3722_poweroff = devm_kzalloc(&pdev->dev, sizeof(*as3722_poweroff),
60 GFP_KERNEL);
61 if (!as3722_poweroff)
62 return -ENOMEM;
63
64 as3722_poweroff->as3722 = dev_get_drvdata(pdev->dev.parent);
65 as3722_poweroff->dev = &pdev->dev;
66 as3722_pm_poweroff = as3722_poweroff;
67 if (!pm_power_off)
68 pm_power_off = as3722_pm_power_off;
69
70 return 0;
71}
72
73static int as3722_poweroff_remove(struct platform_device *pdev)
74{
75 if (pm_power_off == as3722_pm_power_off)
76 pm_power_off = NULL;
77 as3722_pm_poweroff = NULL;
78
79 return 0;
80}
81
82static struct platform_driver as3722_poweroff_driver = {
83 .driver = {
84 .name = "as3722-power-off",
85 .owner = THIS_MODULE,
86 },
87 .probe = as3722_poweroff_probe,
88 .remove = as3722_poweroff_remove,
89};
90
91module_platform_driver(as3722_poweroff_driver);
92
93MODULE_DESCRIPTION("Power off driver for ams AS3722 PMIC Device");
94MODULE_ALIAS("platform:as3722-power-off");
95MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
96MODULE_LICENSE("GPL v2");
diff --git a/include/linux/power/bq2415x_charger.h b/include/linux/power/bq2415x_charger.h
index 8dcc0f46fc0a..50762af8b834 100644
--- a/include/linux/power/bq2415x_charger.h
+++ b/include/linux/power/bq2415x_charger.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * bq2415x charger driver 2 * bq2415x charger driver
3 * 3 *
4 * Copyright (C) 2011-2012 Pali Rohár <pali.rohar@gmail.com> 4 * Copyright (C) 2011-2013 Pali Rohár <pali.rohar@gmail.com>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by 7 * it under the terms of the GNU General Public License as published by
@@ -31,46 +31,9 @@
31 * termination current. It it is less or equal to zero, configuring charge 31 * termination current. It it is less or equal to zero, configuring charge
32 * and termination current will not be possible. 32 * and termination current will not be possible.
33 * 33 *
34 * Function set_mode_hook is needed for automode (setting correct current 34 * For automode support is needed to provide name of power supply device
35 * limit when charger is connected/disconnected or setting boost mode). 35 * in value notify_device. Device driver must immediately report property
36 * When is NULL, automode function is disabled. When is not NULL, it must 36 * POWER_SUPPLY_PROP_CURRENT_MAX when current changed.
37 * have this prototype:
38 *
39 * int (*set_mode_hook)(
40 * void (*hook)(enum bq2415x_mode mode, void *data),
41 * void *data)
42 *
43 * hook is hook function (see below) and data is pointer to driver private
44 * data
45 *
46 * bq2415x driver will call it as:
47 *
48 * platform_data->set_mode_hook(bq2415x_hook_function, bq2415x_device);
49 *
50 * Board/platform function set_mode_hook return non zero value when hook
51 * function was successful registered. Platform code should call that hook
52 * function (which get from pointer, with data) every time when charger
53 * was connected/disconnected or require to enable boost mode. bq2415x
54 * driver then will set correct current limit, enable/disable charger or
55 * boost mode.
56 *
57 * Hook function has this prototype:
58 *
59 * void hook(enum bq2415x_mode mode, void *data);
60 *
61 * mode is bq2415x mode (charger or boost)
62 * data is pointer to driver private data (which get from
63 * set_charger_type_hook)
64 *
65 * When bq driver is being unloaded, it call function:
66 *
67 * platform_data->set_mode_hook(NULL, NULL);
68 *
69 * (hook function and driver private data are NULL)
70 *
71 * After that board/platform code must not call driver hook function! It
72 * is possible that pointer to hook function will not be valid and calling
73 * will cause undefined result.
74 */ 37 */
75 38
76/* Supported modes with maximal current limit */ 39/* Supported modes with maximal current limit */
@@ -89,8 +52,7 @@ struct bq2415x_platform_data {
89 int charge_current; /* mA */ 52 int charge_current; /* mA */
90 int termination_current; /* mA */ 53 int termination_current; /* mA */
91 int resistor_sense; /* m ohm */ 54 int resistor_sense; /* m ohm */
92 int (*set_mode_hook)(void (*hook)(enum bq2415x_mode mode, void *data), 55 const char *notify_device; /* name */
93 void *data);
94}; 56};
95 57
96#endif 58#endif
diff --git a/include/linux/power/charger-manager.h b/include/linux/power/charger-manager.h
index 0e86840eb603..07e7945a1ff2 100644
--- a/include/linux/power/charger-manager.h
+++ b/include/linux/power/charger-manager.h
@@ -37,6 +37,8 @@ enum cm_event_types {
37 CM_EVENT_BATT_FULL, 37 CM_EVENT_BATT_FULL,
38 CM_EVENT_BATT_IN, 38 CM_EVENT_BATT_IN,
39 CM_EVENT_BATT_OUT, 39 CM_EVENT_BATT_OUT,
40 CM_EVENT_BATT_OVERHEAT,
41 CM_EVENT_BATT_COLD,
40 CM_EVENT_EXT_PWR_IN_OUT, 42 CM_EVENT_EXT_PWR_IN_OUT,
41 CM_EVENT_CHG_START_STOP, 43 CM_EVENT_CHG_START_STOP,
42 CM_EVENT_OTHERS, 44 CM_EVENT_OTHERS,
@@ -173,11 +175,10 @@ struct charger_regulator {
173 * @num_charger_regulator: the number of entries in charger_regulators 175 * @num_charger_regulator: the number of entries in charger_regulators
174 * @charger_regulators: array of charger regulators 176 * @charger_regulators: array of charger regulators
175 * @psy_fuel_gauge: the name of power-supply for fuel gauge 177 * @psy_fuel_gauge: the name of power-supply for fuel gauge
176 * @temperature_out_of_range: 178 * @thermal_zone : the name of thermal zone for battery
177 * Determine whether the status is overheat or cold or normal. 179 * @temp_min : Minimum battery temperature for charging.
178 * return_value > 0: overheat 180 * @temp_max : Maximum battery temperature for charging.
179 * return_value == 0: normal 181 * @temp_diff : Temperature diffential to restart charging.
180 * return_value < 0: cold
181 * @measure_battery_temp: 182 * @measure_battery_temp:
182 * true: measure battery temperature 183 * true: measure battery temperature
183 * false: measure ambient temperature 184 * false: measure ambient temperature
@@ -190,7 +191,7 @@ struct charger_regulator {
190 * max_duration_ms', cm start charging. 191 * max_duration_ms', cm start charging.
191 */ 192 */
192struct charger_desc { 193struct charger_desc {
193 char *psy_name; 194 const char *psy_name;
194 195
195 enum polling_modes polling_mode; 196 enum polling_modes polling_mode;
196 unsigned int polling_interval_ms; 197 unsigned int polling_interval_ms;
@@ -203,18 +204,23 @@ struct charger_desc {
203 204
204 enum data_source battery_present; 205 enum data_source battery_present;
205 206
206 char **psy_charger_stat; 207 const char **psy_charger_stat;
207 208
208 int num_charger_regulators; 209 int num_charger_regulators;
209 struct charger_regulator *charger_regulators; 210 struct charger_regulator *charger_regulators;
210 211
211 char *psy_fuel_gauge; 212 const char *psy_fuel_gauge;
213
214 const char *thermal_zone;
215
216 int temp_min;
217 int temp_max;
218 int temp_diff;
212 219
213 int (*temperature_out_of_range)(int *mC);
214 bool measure_battery_temp; 220 bool measure_battery_temp;
215 221
216 u64 charging_max_duration_ms; 222 u32 charging_max_duration_ms;
217 u64 discharging_max_duration_ms; 223 u32 discharging_max_duration_ms;
218}; 224};
219 225
220#define PSY_NAME_MAX 30 226#define PSY_NAME_MAX 30
@@ -226,13 +232,13 @@ struct charger_desc {
226 * @desc: instance of charger_desc 232 * @desc: instance of charger_desc
227 * @fuel_gauge: power_supply for fuel gauge 233 * @fuel_gauge: power_supply for fuel gauge
228 * @charger_stat: array of power_supply for chargers 234 * @charger_stat: array of power_supply for chargers
235 * @tzd_batt : thermal zone device for battery
229 * @charger_enabled: the state of charger 236 * @charger_enabled: the state of charger
230 * @fullbatt_vchk_jiffies_at: 237 * @fullbatt_vchk_jiffies_at:
231 * jiffies at the time full battery check will occur. 238 * jiffies at the time full battery check will occur.
232 * @fullbatt_vchk_work: work queue for full battery check 239 * @fullbatt_vchk_work: work queue for full battery check
233 * @emergency_stop: 240 * @emergency_stop:
234 * When setting true, stop charging 241 * When setting true, stop charging
235 * @last_temp_mC: the measured temperature in milli-Celsius
236 * @psy_name_buf: the name of power-supply-class for charger manager 242 * @psy_name_buf: the name of power-supply-class for charger manager
237 * @charger_psy: power_supply for charger manager 243 * @charger_psy: power_supply for charger manager
238 * @status_save_ext_pwr_inserted: 244 * @status_save_ext_pwr_inserted:
@@ -250,13 +256,15 @@ struct charger_manager {
250 struct power_supply *fuel_gauge; 256 struct power_supply *fuel_gauge;
251 struct power_supply **charger_stat; 257 struct power_supply **charger_stat;
252 258
259#ifdef CONFIG_THERMAL
260 struct thermal_zone_device *tzd_batt;
261#endif
253 bool charger_enabled; 262 bool charger_enabled;
254 263
255 unsigned long fullbatt_vchk_jiffies_at; 264 unsigned long fullbatt_vchk_jiffies_at;
256 struct delayed_work fullbatt_vchk_work; 265 struct delayed_work fullbatt_vchk_work;
257 266
258 int emergency_stop; 267 int emergency_stop;
259 int last_temp_mC;
260 268
261 char psy_name_buf[PSY_NAME_MAX + 1]; 269 char psy_name_buf[PSY_NAME_MAX + 1];
262 struct power_supply charger_psy; 270 struct power_supply charger_psy;
diff --git a/include/linux/power/isp1704_charger.h b/include/linux/power/isp1704_charger.h
index 68096a6aa2d7..0105d9e7af85 100644
--- a/include/linux/power/isp1704_charger.h
+++ b/include/linux/power/isp1704_charger.h
@@ -24,6 +24,7 @@
24 24
25struct isp1704_charger_data { 25struct isp1704_charger_data {
26 void (*set_power)(bool on); 26 void (*set_power)(bool on);
27 int enable_gpio;
27}; 28};
28 29
29#endif 30#endif
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 5c2600630dc9..c9dc4e09854c 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -16,6 +16,7 @@
16#include <linux/workqueue.h> 16#include <linux/workqueue.h>
17#include <linux/leds.h> 17#include <linux/leds.h>
18#include <linux/spinlock.h> 18#include <linux/spinlock.h>
19#include <linux/notifier.h>
19 20
20struct device; 21struct device;
21 22
@@ -158,6 +159,10 @@ enum power_supply_type {
158 POWER_SUPPLY_TYPE_USB_ACA, /* Accessory Charger Adapters */ 159 POWER_SUPPLY_TYPE_USB_ACA, /* Accessory Charger Adapters */
159}; 160};
160 161
162enum power_supply_notifier_events {
163 PSY_EVENT_PROP_CHANGED,
164};
165
161union power_supply_propval { 166union power_supply_propval {
162 int intval; 167 int intval;
163 const char *strval; 168 const char *strval;
@@ -235,7 +240,18 @@ struct power_supply_info {
235 int use_for_apm; 240 int use_for_apm;
236}; 241};
237 242
243extern struct atomic_notifier_head power_supply_notifier;
244extern int power_supply_reg_notifier(struct notifier_block *nb);
245extern void power_supply_unreg_notifier(struct notifier_block *nb);
238extern struct power_supply *power_supply_get_by_name(const char *name); 246extern struct power_supply *power_supply_get_by_name(const char *name);
247#ifdef CONFIG_OF
248extern struct power_supply *power_supply_get_by_phandle(struct device_node *np,
249 const char *property);
250#else /* !CONFIG_OF */
251static inline struct power_supply *
252power_supply_get_by_phandle(struct device_node *np, const char *property)
253{ return NULL; }
254#endif /* CONFIG_OF */
239extern void power_supply_changed(struct power_supply *psy); 255extern void power_supply_changed(struct power_supply *psy);
240extern int power_supply_am_i_supplied(struct power_supply *psy); 256extern int power_supply_am_i_supplied(struct power_supply *psy);
241extern int power_supply_set_battery_charged(struct power_supply *psy); 257extern int power_supply_set_battery_charged(struct power_supply *psy);