History

charger-manager: Use EXTCON Subsystem to detect charger cables for charging

This patch support that charger-manager use EXTCON(External Connector) Subsystem to detect the state of charger cables for enabling or disabling charger(regulator) and select the charger cable for charging among a number of external cable according to policy of H/W board.

Chanwoo Choi committed 14 years ago

Commit bee737b1 parent 85a392d2 files · +179 −17Browse files

Unified · Split

2 files
  1. drivers/power/charger-manager.c +121 −16
  2. include/linux/power/charger-manager.h +58 −1
drivers/power/charger-manager.c+121−16
@@ -271,16 +271,13 @@ static int try_charger_enable(struct charger_manager *cm, bool enable) · 270 unmodified lines
271271 if (enable) {
272272 if (cm->emergency_stop)
273273 return -EAGAIN;
274− err = regulator_bulk_enable(desc->num_charger_regulators,
275− desc->charger_regulators);
274+ for (i = 0 ; i < desc->num_charger_regulators ; i++)
275+ regulator_enable(desc->charger_regulators[i].consumer);
276276 } else {
277277 /*
278278 * Abnormal battery state - Stop charging forcibly,
279279 * even if charger was enabled at the other places
280280 */
281− err = regulator_bulk_disable(desc->num_charger_regulators,
282− desc->charger_regulators);
283−
284281 for (i = 0; i < desc->num_charger_regulators; i++) {
285282 if (regulator_is_enabled(
286283 desc->charger_regulators[i].consumer)) {
@@ -288,7 +285,7 @@ static int try_charger_enable(struct charger_manager *cm, bool enable) · 1 unmodified line
288285 desc->charger_regulators[i].consumer);
289286 dev_warn(cm->dev,
290287 "Disable regulator(%s) forcibly.\n",
291− desc->charger_regulators[i].supply);
288+ desc->charger_regulators[i].regulator_name);
292289 }
293290 }
294291 }
@@ -994,11 +991,77 @@ int setup_charger_manager(struct charger_global_desc *gd) · 699 unmodified lines
994991 }
995992 EXPORT_SYMBOL_GPL(setup_charger_manager);
996993
994+/**
995+ * charger_extcon_work - enable/diable charger according to the state
996+ * of charger cable
997+ *
998+ * @work: work_struct of the function charger_extcon_work.
999+ */
1000+static void charger_extcon_work(struct work_struct *work)
1001+{
1002+ struct charger_cable *cable =
1003+ container_of(work, struct charger_cable, wq);
1004+
1005+ try_charger_enable(cable->cm, cable->attached);
1006+}
1007+
1008+/**
1009+ * charger_extcon_notifier - receive the state of charger cable
1010+ * when registered cable is attached or detached.
1011+ *
1012+ * @self: the notifier block of the charger_extcon_notifier.
1013+ * @event: the cable state.
1014+ * @ptr: the data pointer of notifier block.
1015+ */
1016+static int charger_extcon_notifier(struct notifier_block *self,
1017+ unsigned long event, void *ptr)
1018+{
1019+ struct charger_cable *cable =
1020+ container_of(self, struct charger_cable, nb);
1021+
1022+ cable->attached = event;
1023+ schedule_work(&cable->wq);
1024+
1025+ return NOTIFY_DONE;
1026+}
1027+
1028+/**
1029+ * charger_extcon_init - register external connector to use it
1030+ * as the charger cable
1031+ *
1032+ * @cm: the Charger Manager representing the battery.
1033+ * @cable: the Charger cable representing the external connector.
1034+ */
1035+static int charger_extcon_init(struct charger_manager *cm,
1036+ struct charger_cable *cable)
1037+{
1038+ int ret = 0;
1039+
1040+ /*
1041+ * Charger manager use Extcon framework to identify
1042+ * the charger cable among various external connector
1043+ * cable (e.g., TA, USB, MHL, Dock).
1044+ */
1045+ INIT_WORK(&cable->wq, charger_extcon_work);
1046+ cable->nb.notifier_call = charger_extcon_notifier;
1047+ ret = extcon_register_interest(&cable->extcon_dev,
1048+ cable->extcon_name, cable->name, &cable->nb);
1049+ if (ret < 0) {
1050+ pr_info("Cannot register extcon_dev for %s(cable: %s).\n",
1051+ cable->extcon_name,
1052+ cable->name);
1053+ ret = -EINVAL;
1054+ }
1055+
1056+ return ret;
1057+}
1058+
9971059 static int charger_manager_probe(struct platform_device *pdev)
9981060 {
9991061 struct charger_desc *desc = dev_get_platdata(&pdev->dev);
10001062 struct charger_manager *cm;
10011063 int ret = 0, i = 0;
1064+ int j = 0;
10021065 union power_supply_propval val;
10031066
10041067 if (g_desc && !rtc_dev && g_desc->rtc_name) {
@@ -1167,11 +1230,31 @@ static int charger_manager_probe(struct platform_device *pdev) · 162 unmodified lines
11671230 goto err_register;
11681231 }
11691232
1170− ret = regulator_bulk_get(&pdev->dev, desc->num_charger_regulators,
1171− desc->charger_regulators);
1172− if (ret) {
1173− dev_err(&pdev->dev, "Cannot get charger regulators.\n");
1174− goto err_bulk_get;
1233+ for (i = 0 ; i < desc->num_charger_regulators ; i++) {
1234+ struct charger_regulator *charger
1235+ = &desc->charger_regulators[i];
1236+
1237+ charger->consumer = regulator_get(&pdev->dev,
1238+ charger->regulator_name);
1239+ if (charger->consumer == NULL) {
1240+ dev_err(&pdev->dev, "Cannot find charger(%s)n",
1241+ charger->regulator_name);
1242+ ret = -EINVAL;
1243+ goto err_chg_get;
1244+ }
1245+
1246+ for (j = 0 ; j < charger->num_cables ; j++) {
1247+ struct charger_cable *cable = &charger->cables[j];
1248+
1249+ ret = charger_extcon_init(cm, cable);
1250+ if (ret < 0) {
1251+ dev_err(&pdev->dev, "Cannot find charger(%s)n",
1252+ charger->regulator_name);
1253+ goto err_extcon;
1254+ }
1255+ cable->charger = charger;
1256+ cable->cm = cm;
1257+ }
11751258 }
11761259
11771260 ret = try_charger_enable(cm, true);
@@ -1197,9 +1280,19 @@ static int charger_manager_probe(struct platform_device *pdev) · 19 unmodified lines
11971280 return 0;
11981281
11991282 err_chg_enable:
1200− regulator_bulk_free(desc->num_charger_regulators,
1201− desc->charger_regulators);
1202−err_bulk_get:
1283+err_extcon:
1284+ for (i = 0 ; i < desc->num_charger_regulators ; i++) {
1285+ struct charger_regulator *charger
1286+ = &desc->charger_regulators[i];
1287+ for (j = 0 ; j < charger->num_cables ; j++) {
1288+ struct charger_cable *cable = &charger->cables[j];
1289+ extcon_unregister_interest(&cable->extcon_dev);
1290+ }
1291+ }
1292+err_chg_get:
1293+ for (i = 0 ; i < desc->num_charger_regulators ; i++)
1294+ regulator_put(desc->charger_regulators[i].consumer);
1295+
12031296 power_supply_unregister(&cm->charger_psy);
12041297 err_register:
12051298 kfree(cm->charger_psy.properties);
@@ -1218,6 +1311,8 @@ static int __devexit charger_manager_remove(struct platform_device *pdev) · 12 unmodified lines
12181311 {
12191312 struct charger_manager *cm = platform_get_drvdata(pdev);
12201313 struct charger_desc *desc = cm->desc;
1314+ int i = 0;
1315+ int j = 0;
12211316
12221317 /* Remove from the list */
12231318 mutex_lock(&cm_list_mtx);
@@ -1229,8 +1324,18 @@ static int __devexit charger_manager_remove(struct platform_device *pdev) · 5 unmodified lines
12291324 if (delayed_work_pending(&cm_monitor_work))
12301325 cancel_delayed_work_sync(&cm_monitor_work);
12311326
1232− regulator_bulk_free(desc->num_charger_regulators,
1233− desc->charger_regulators);
1327+ for (i = 0 ; i < desc->num_charger_regulators ; i++) {
1328+ struct charger_regulator *charger
1329+ = &desc->charger_regulators[i];
1330+ for (j = 0 ; j < charger->num_cables ; j++) {
1331+ struct charger_cable *cable = &charger->cables[j];
1332+ extcon_unregister_interest(&cable->extcon_dev);
1333+ }
1334+ }
1335+
1336+ for (i = 0 ; i < desc->num_charger_regulators ; i++)
1337+ regulator_put(desc->charger_regulators[i].consumer);
1338+
12341339 power_supply_unregister(&cm->charger_psy);
12351340
12361341 try_charger_enable(cm, false);
include/linux/power/charger-manager.h+58−1
@@ -16,6 +16,7 @@ · 15 unmodified lines
1616 #define _CHARGER_MANAGER_H
1717
1818 #include <linux/power_supply.h>
19+#include <linux/extcon.h>
1920
2021 enum data_source {
2122 CM_BATTERY_PRESENT,
@@ -64,6 +65,62 @@ struct charger_global_desc { · 42 unmodified lines
6465 bool assume_timer_stops_in_suspend;
6566 };
6667
68+/**
69+ * struct charger_cable
70+ * @extcon_name: the name of extcon device.
71+ * @name: the name of charger cable(external connector).
72+ * @extcon_dev: the extcon device.
73+ * @wq: the workqueue to control charger according to the state of
74+ * charger cable. If charger cable is attached, enable charger.
75+ * But if charger cable is detached, disable charger.
76+ * @nb: the notifier block to receive changed state from EXTCON
77+ * (External Connector) when charger cable is attached/detached.
78+ * @attached: the state of charger cable.
79+ * true: the charger cable is attached
80+ * false: the charger cable is detached
81+ * @charger: the instance of struct charger_regulator.
82+ * @cm: the Charger Manager representing the battery.
83+ */
84+struct charger_cable {
85+ const char *extcon_name;
86+ const char *name;
87+
88+ /* The charger-manager use Exton framework*/
89+ struct extcon_specific_cable_nb extcon_dev;
90+ struct work_struct wq;
91+ struct notifier_block nb;
92+
93+ /* The state of charger cable */
94+ bool attached;
95+
96+ struct charger_regulator *charger;
97+ struct charger_manager *cm;
98+};
99+
100+/**
101+ * struct charger_regulator
102+ * @regulator_name: the name of regulator for using charger.
103+ * @consumer: the regulator consumer for the charger.
104+ * @cables:
105+ * the array of charger cables to enable/disable charger
106+ * and set current limit according to constratint data of
107+ * struct charger_cable if only charger cable included
108+ * in the array of charger cables is attached/detached.
109+ * @num_cables: the number of charger cables.
110+ */
111+struct charger_regulator {
112+ /* The name of regulator for charging */
113+ const char *regulator_name;
114+ struct regulator *consumer;
115+
116+ /*
117+ * Store constraint information related to current limit,
118+ * each cable have different condition for charging.
119+ */
120+ struct charger_cable *cables;
121+ int num_cables;
122+};
123+
67124 /**
68125 * struct charger_desc
69126 * @psy_name: the name of power-supply-class for charger manager
@@ -109,7 +166,7 @@ struct charger_desc { · 39 unmodified lines
109166 char **psy_charger_stat;
110167
111168 int num_charger_regulators;
112− struct regulator_bulk_data *charger_regulators;
169+ struct charger_regulator *charger_regulators;
113170
114171 char *psy_fuel_gauge;
115172

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t