diff options
-rw-r--r-- | Documentation/devicetree/bindings/mfd/as3722.txt | 11 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/power/isp1704.txt | 17 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/power_supply/charger-manager.txt | 81 | ||||
-rw-r--r-- | MAINTAINERS | 2 | ||||
-rw-r--r-- | drivers/power/Kconfig | 7 | ||||
-rw-r--r-- | drivers/power/Makefile | 1 | ||||
-rw-r--r-- | drivers/power/bq2415x_charger.c | 121 | ||||
-rw-r--r-- | drivers/power/charger-manager.c | 299 | ||||
-rw-r--r-- | drivers/power/gpio-charger.c | 19 | ||||
-rw-r--r-- | drivers/power/isp1704_charger.c | 54 | ||||
-rw-r--r-- | drivers/power/max14577_charger.c | 311 | ||||
-rw-r--r-- | drivers/power/max17042_battery.c | 6 | ||||
-rw-r--r-- | drivers/power/power_supply_core.c | 44 | ||||
-rw-r--r-- | drivers/power/reset/Kconfig | 6 | ||||
-rw-r--r-- | drivers/power/reset/Makefile | 1 | ||||
-rw-r--r-- | drivers/power/reset/as3722-poweroff.c | 96 | ||||
-rw-r--r-- | include/linux/power/bq2415x_charger.h | 48 | ||||
-rw-r--r-- | include/linux/power/charger-manager.h | 34 | ||||
-rw-r--r-- | include/linux/power/isp1704_charger.h | 1 | ||||
-rw-r--r-- | include/linux/power_supply.h | 16 |
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 | ||
115 | Power-off: | ||
116 | ========= | ||
117 | AS3722 supports the system power off by turning off all its rail. This | ||
118 | is provided through pm_power_off. | ||
119 | The device node should have the following properties to enable this | ||
120 | functionality | ||
121 | ams,system-power-controller: Boolean, to enable the power off functionality | ||
122 | through this device. | ||
123 | |||
115 | Example: | 124 | Example: |
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 @@ | |||
1 | Binding for NXP ISP1704 USB Charger Detection | ||
2 | |||
3 | Required 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 | |||
11 | Example: | ||
12 | |||
13 | isp1704 { | ||
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 @@ | |||
1 | charger-manager bindings | ||
2 | ~~~~~~~~~~~~~~~~~~~~~~~~ | ||
3 | |||
4 | Required 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 | |||
18 | Optional 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 | |||
32 | Example : | ||
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* | |||
6712 | F: kernel/*timer* | 6712 | F: kernel/*timer* |
6713 | 6713 | ||
6714 | POWER SUPPLY CLASS/SUBSYSTEM and DRIVERS | 6714 | POWER SUPPLY CLASS/SUBSYSTEM and DRIVERS |
6715 | M: Anton Vorontsov <anton@enomsg.org> | 6715 | M: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> |
6716 | M: David Woodhouse <dwmw2@infradead.org> | 6716 | M: David Woodhouse <dwmw2@infradead.org> |
6717 | T: git git://git.infradead.org/battery-2.6.git | 6717 | T: git git://git.infradead.org/battery-2.6.git |
6718 | S: Maintained | 6718 | S: 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 | ||
320 | config 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 | |||
320 | config CHARGER_MAX8997 | 327 | config 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 | |||
48 | obj-$(CONFIG_CHARGER_LP8788) += lp8788-charger.o | 48 | obj-$(CONFIG_CHARGER_LP8788) += lp8788-charger.o |
49 | obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o | 49 | obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o |
50 | obj-$(CONFIG_CHARGER_MANAGER) += charger-manager.o | 50 | obj-$(CONFIG_CHARGER_MANAGER) += charger-manager.o |
51 | obj-$(CONFIG_CHARGER_MAX14577) += max14577_charger.o | ||
51 | obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o | 52 | obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o |
52 | obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o | 53 | obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o |
53 | obj-$(CONFIG_CHARGER_BQ2415X) += bq2415x_charger.o | 54 | obj-$(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 */ | 800 | static int bq2415x_notifier_call(struct notifier_block *nb, |
799 | static 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 | ||
1671 | error_5: | ||
1597 | error_4: | 1672 | error_4: |
1598 | bq2415x_sysfs_exit(bq); | 1673 | bq2415x_sysfs_exit(bq); |
1599 | error_3: | 1674 | error_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 | ||
29 | static const char * const default_event_names[] = { | 38 | static 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 | ||
554 | static 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 | |||
575 | static 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 | */ |
550 | static bool _cm_monitor(struct charger_manager *cm) | 615 | static 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 | ||
1488 | static 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 | |||
1532 | static struct of_device_id charger_manager_match[] = { | ||
1533 | { | ||
1534 | .compatible = "charger-manager", | ||
1535 | }, | ||
1536 | {}, | ||
1537 | }; | ||
1538 | |||
1539 | static 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 | |||
1655 | static 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 | |||
1442 | static int charger_manager_probe(struct platform_device *pdev) | 1662 | static 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 @@ | |||
28 | struct gpio_charger { | 28 | struct 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 | ||
141 | err_gpio_free: | 144 | err_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 |
165 | static 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 | |||
162 | static int gpio_charger_resume(struct device *dev) | 176 | static 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 | ||
173 | static SIMPLE_DEV_PM_OPS(gpio_charger_pm_ops, NULL, gpio_charger_resume); | 189 | static SIMPLE_DEV_PM_OPS(gpio_charger_pm_ops, |
190 | gpio_charger_suspend, gpio_charger_resume); | ||
174 | 191 | ||
175 | static struct platform_driver gpio_charger_driver = { | 192 | static 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); |
465 | fail1: | 504 | fail1: |
466 | isp1704_charger_set_power(isp, 0); | 505 | isp1704_charger_set_power(isp, 0); |
467 | usb_put_phy(isp->phy); | ||
468 | fail0: | 506 | fail0: |
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 | ||
524 | static const struct of_device_id omap_isp1704_of_match[] = { | ||
525 | { .compatible = "nxp,isp1704", }, | ||
526 | {}, | ||
527 | }; | ||
528 | MODULE_DEVICE_TABLE(of, omap_isp1704_of_match); | ||
529 | #endif | ||
530 | |||
486 | static struct platform_driver isp1704_charger_driver = { | 531 | static 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 | |||
23 | struct 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 | |||
32 | static 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, ®_data); | ||
50 | if ((reg_data & CHGCTRL2_MBCHOSTEN_MASK) == 0) | ||
51 | goto state_set; | ||
52 | |||
53 | max14577_read_reg(rmap, MAX14577_CHG_REG_STATUS3, ®_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 | |||
63 | state_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 | */ | ||
73 | static 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 | |||
88 | static 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, ®_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 | */ | ||
116 | static 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, ®_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, ®_data); | ||
130 | if (reg_data & STATUS3_OVP_MASK) { | ||
131 | state = POWER_SUPPLY_HEALTH_OVERVOLTAGE; | ||
132 | goto state_set; | ||
133 | } | ||
134 | |||
135 | state_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 | */ | ||
145 | static 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 | */ | ||
155 | static 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 */ | ||
208 | static 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 | |||
218 | static const char *model_name = "MAX14577"; | ||
219 | static const char *manufacturer = "Maxim Integrated"; | ||
220 | |||
221 | static 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 | |||
259 | static 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 | |||
290 | static 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 | |||
299 | static 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 | }; | ||
307 | module_platform_driver(max14577_charger_driver); | ||
308 | |||
309 | MODULE_AUTHOR("Krzysztof Kozlowski <k.kozlowski@samsung.com>"); | ||
310 | MODULE_DESCRIPTION("MAXIM 14577 charger driver"); | ||
311 | MODULE_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 @@ | |||
24 | struct class *power_supply_class; | 25 | struct class *power_supply_class; |
25 | EXPORT_SYMBOL_GPL(power_supply_class); | 26 | EXPORT_SYMBOL_GPL(power_supply_class); |
26 | 27 | ||
28 | ATOMIC_NOTIFIER_HEAD(power_supply_notifier); | ||
29 | EXPORT_SYMBOL_GPL(power_supply_notifier); | ||
30 | |||
27 | static struct device_type power_supply_dev_type; | 31 | static struct device_type power_supply_dev_type; |
28 | 32 | ||
29 | static bool __power_supply_is_supplied_by(struct power_supply *supplier, | 33 | static 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 | } |
336 | EXPORT_SYMBOL_GPL(power_supply_get_by_name); | 342 | EXPORT_SYMBOL_GPL(power_supply_get_by_name); |
337 | 343 | ||
344 | #ifdef CONFIG_OF | ||
345 | static int power_supply_match_device_node(struct device *dev, const void *data) | ||
346 | { | ||
347 | return dev->parent && dev->parent->of_node == data; | ||
348 | } | ||
349 | |||
350 | struct 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 | } | ||
367 | EXPORT_SYMBOL_GPL(power_supply_get_by_phandle); | ||
368 | #endif /* CONFIG_OF */ | ||
369 | |||
338 | int power_supply_powers(struct power_supply *psy, struct device *dev) | 370 | int 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 | ||
382 | int power_supply_reg_notifier(struct notifier_block *nb) | ||
383 | { | ||
384 | return atomic_notifier_chain_register(&power_supply_notifier, nb); | ||
385 | } | ||
386 | EXPORT_SYMBOL_GPL(power_supply_reg_notifier); | ||
387 | |||
388 | void power_supply_unreg_notifier(struct notifier_block *nb) | ||
389 | { | ||
390 | atomic_notifier_chain_unregister(&power_supply_notifier, nb); | ||
391 | } | ||
392 | EXPORT_SYMBOL_GPL(power_supply_unreg_notifier); | ||
393 | |||
350 | #ifdef CONFIG_THERMAL | 394 | #ifdef CONFIG_THERMAL |
351 | static int power_supply_read_temp(struct thermal_zone_device *tzd, | 395 | static 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 | ||
9 | config 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 | |||
9 | config POWER_RESET_GPIO | 15 | config 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 @@ | |||
1 | obj-$(CONFIG_POWER_RESET_AS3722) += as3722-poweroff.o | ||
1 | obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o | 2 | obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o |
2 | obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o | 3 | obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o |
3 | obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o | 4 | obj-$(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 | |||
25 | struct as3722_poweroff { | ||
26 | struct device *dev; | ||
27 | struct as3722 *as3722; | ||
28 | }; | ||
29 | |||
30 | static struct as3722_poweroff *as3722_pm_poweroff; | ||
31 | |||
32 | static 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 | |||
48 | static 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 | |||
73 | static 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 | |||
82 | static 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 | |||
91 | module_platform_driver(as3722_poweroff_driver); | ||
92 | |||
93 | MODULE_DESCRIPTION("Power off driver for ams AS3722 PMIC Device"); | ||
94 | MODULE_ALIAS("platform:as3722-power-off"); | ||
95 | MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>"); | ||
96 | MODULE_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 | */ |
192 | struct charger_desc { | 193 | struct 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 | ||
25 | struct isp1704_charger_data { | 25 | struct 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 | ||
20 | struct device; | 21 | struct 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 | ||
162 | enum power_supply_notifier_events { | ||
163 | PSY_EVENT_PROP_CHANGED, | ||
164 | }; | ||
165 | |||
161 | union power_supply_propval { | 166 | union 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 | ||
243 | extern struct atomic_notifier_head power_supply_notifier; | ||
244 | extern int power_supply_reg_notifier(struct notifier_block *nb); | ||
245 | extern void power_supply_unreg_notifier(struct notifier_block *nb); | ||
238 | extern struct power_supply *power_supply_get_by_name(const char *name); | 246 | extern struct power_supply *power_supply_get_by_name(const char *name); |
247 | #ifdef CONFIG_OF | ||
248 | extern struct power_supply *power_supply_get_by_phandle(struct device_node *np, | ||
249 | const char *property); | ||
250 | #else /* !CONFIG_OF */ | ||
251 | static inline struct power_supply * | ||
252 | power_supply_get_by_phandle(struct device_node *np, const char *property) | ||
253 | { return NULL; } | ||
254 | #endif /* CONFIG_OF */ | ||
239 | extern void power_supply_changed(struct power_supply *psy); | 255 | extern void power_supply_changed(struct power_supply *psy); |
240 | extern int power_supply_am_i_supplied(struct power_supply *psy); | 256 | extern int power_supply_am_i_supplied(struct power_supply *psy); |
241 | extern int power_supply_set_battery_charged(struct power_supply *psy); | 257 | extern int power_supply_set_battery_charged(struct power_supply *psy); |