aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power/charger-manager.c
diff options
context:
space:
mode:
authorChanwoo Choi <cw00.choi@samsung.com>2012-11-22 02:54:26 -0500
committerAnton Vorontsov <anton.vorontsov@linaro.org>2013-01-05 17:00:09 -0500
commit41468a11199212f092cb4c071626785db6a32393 (patch)
tree17316fec71046352f67a5bc596efc6a7ffb7236f /drivers/power/charger-manager.c
parentd1c3ed669a2d452cacfb48c2d171a1f364dae2ed (diff)
charger-manager: Split _probe funtion to make the code more clean
This patch split _probe function for readability because _probe function is longer than 400 line. Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com> Signed-off-by: Myungjoo Ham <myungjoo.ham@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>
Diffstat (limited to 'drivers/power/charger-manager.c')
-rw-r--r--drivers/power/charger-manager.c279
1 files changed, 168 insertions, 111 deletions
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
index 6ba047f5ac2c..029732d83090 100644
--- a/drivers/power/charger-manager.c
+++ b/drivers/power/charger-manager.c
@@ -1215,6 +1215,55 @@ static int charger_extcon_init(struct charger_manager *cm,
1215 return ret; 1215 return ret;
1216} 1216}
1217 1217
1218/**
1219 * charger_manager_register_extcon - Register extcon device to recevie state
1220 * of charger cable.
1221 * @cm: the Charger Manager representing the battery.
1222 *
1223 * This function support EXTCON(External Connector) subsystem to detect the
1224 * state of charger cables for enabling or disabling charger(regulator) and
1225 * select the charger cable for charging among a number of external cable
1226 * according to policy of H/W board.
1227 */
1228static int charger_manager_register_extcon(struct charger_manager *cm)
1229{
1230 struct charger_desc *desc = cm->desc;
1231 struct charger_regulator *charger;
1232 int ret = 0;
1233 int i;
1234 int j;
1235
1236 for (i = 0; i < desc->num_charger_regulators; i++) {
1237 charger = &desc->charger_regulators[i];
1238
1239 charger->consumer = regulator_get(cm->dev,
1240 charger->regulator_name);
1241 if (charger->consumer == NULL) {
1242 dev_err(cm->dev, "Cannot find charger(%s)n",
1243 charger->regulator_name);
1244 ret = -EINVAL;
1245 goto err;
1246 }
1247 charger->cm = cm;
1248
1249 for (j = 0; j < charger->num_cables; j++) {
1250 struct charger_cable *cable = &charger->cables[j];
1251
1252 ret = charger_extcon_init(cm, cable);
1253 if (ret < 0) {
1254 dev_err(cm->dev, "Cannot initialize charger(%s)n",
1255 charger->regulator_name);
1256 goto err;
1257 }
1258 cable->charger = charger;
1259 cable->cm = cm;
1260 }
1261 }
1262
1263err:
1264 return ret;
1265}
1266
1218/* help function of sysfs node to control charger(regulator) */ 1267/* help function of sysfs node to control charger(regulator) */
1219static ssize_t charger_name_show(struct device *dev, 1268static ssize_t charger_name_show(struct device *dev,
1220 struct device_attribute *attr, char *buf) 1269 struct device_attribute *attr, char *buf)
@@ -1274,7 +1323,7 @@ static ssize_t charger_externally_control_store(struct device *dev,
1274 1323
1275 for (i = 0; i < desc->num_charger_regulators; i++) { 1324 for (i = 0; i < desc->num_charger_regulators; i++) {
1276 if (&desc->charger_regulators[i] != charger && 1325 if (&desc->charger_regulators[i] != charger &&
1277 !desc->charger_regulators[i].externally_control) { 1326 !desc->charger_regulators[i].externally_control) {
1278 /* 1327 /*
1279 * At least, one charger is controlled by 1328 * At least, one charger is controlled by
1280 * charger-manager 1329 * charger-manager
@@ -1303,13 +1352,107 @@ static ssize_t charger_externally_control_store(struct device *dev,
1303 return count; 1352 return count;
1304} 1353}
1305 1354
1355/**
1356 * charger_manager_register_sysfs - Register sysfs entry for each charger
1357 * @cm: the Charger Manager representing the battery.
1358 *
1359 * This function add sysfs entry for charger(regulator) to control charger from
1360 * user-space. If some development board use one more chargers for charging
1361 * but only need one charger on specific case which is dependent on user
1362 * scenario or hardware restrictions, the user enter 1 or 0(zero) to '/sys/
1363 * class/power_supply/battery/charger.[index]/externally_control'. For example,
1364 * if user enter 1 to 'sys/class/power_supply/battery/charger.[index]/
1365 * externally_control, this charger isn't controlled from charger-manager and
1366 * always stay off state of regulator.
1367 */
1368static int charger_manager_register_sysfs(struct charger_manager *cm)
1369{
1370 struct charger_desc *desc = cm->desc;
1371 struct charger_regulator *charger;
1372 int chargers_externally_control = 1;
1373 char buf[11];
1374 char *str;
1375 int ret = 0;
1376 int i;
1377
1378 /* Create sysfs entry to control charger(regulator) */
1379 for (i = 0; i < desc->num_charger_regulators; i++) {
1380 charger = &desc->charger_regulators[i];
1381
1382 snprintf(buf, 10, "charger.%d", i);
1383 str = kzalloc(sizeof(char) * (strlen(buf) + 1), GFP_KERNEL);
1384 if (!str) {
1385 dev_err(cm->dev, "Cannot allocate memory: %s\n",
1386 charger->regulator_name);
1387 ret = -ENOMEM;
1388 goto err;
1389 }
1390 strcpy(str, buf);
1391
1392 charger->attrs[0] = &charger->attr_name.attr;
1393 charger->attrs[1] = &charger->attr_state.attr;
1394 charger->attrs[2] = &charger->attr_externally_control.attr;
1395 charger->attrs[3] = NULL;
1396 charger->attr_g.name = str;
1397 charger->attr_g.attrs = charger->attrs;
1398
1399 sysfs_attr_init(&charger->attr_name.attr);
1400 charger->attr_name.attr.name = "name";
1401 charger->attr_name.attr.mode = 0444;
1402 charger->attr_name.show = charger_name_show;
1403
1404 sysfs_attr_init(&charger->attr_state.attr);
1405 charger->attr_state.attr.name = "state";
1406 charger->attr_state.attr.mode = 0444;
1407 charger->attr_state.show = charger_state_show;
1408
1409 sysfs_attr_init(&charger->attr_externally_control.attr);
1410 charger->attr_externally_control.attr.name
1411 = "externally_control";
1412 charger->attr_externally_control.attr.mode = 0644;
1413 charger->attr_externally_control.show
1414 = charger_externally_control_show;
1415 charger->attr_externally_control.store
1416 = charger_externally_control_store;
1417
1418 if (!desc->charger_regulators[i].externally_control ||
1419 !chargers_externally_control)
1420 chargers_externally_control = 0;
1421
1422 dev_info(cm->dev, "'%s' regulator's externally_control"
1423 "is %d\n", charger->regulator_name,
1424 charger->externally_control);
1425
1426 ret = sysfs_create_group(&cm->charger_psy.dev->kobj,
1427 &charger->attr_g);
1428 if (ret < 0) {
1429 dev_err(cm->dev, "Cannot create sysfs entry"
1430 "of %s regulator\n",
1431 charger->regulator_name);
1432 ret = -EINVAL;
1433 goto err;
1434 }
1435 }
1436
1437 if (chargers_externally_control) {
1438 dev_err(cm->dev, "Cannot register regulator because "
1439 "charger-manager must need at least "
1440 "one charger for charging battery\n");
1441
1442 ret = -EINVAL;
1443 goto err;
1444 }
1445
1446err:
1447 return ret;
1448}
1449
1306static int charger_manager_probe(struct platform_device *pdev) 1450static int charger_manager_probe(struct platform_device *pdev)
1307{ 1451{
1308 struct charger_desc *desc = dev_get_platdata(&pdev->dev); 1452 struct charger_desc *desc = dev_get_platdata(&pdev->dev);
1309 struct charger_manager *cm; 1453 struct charger_manager *cm;
1310 int ret = 0, i = 0; 1454 int ret = 0, i = 0;
1311 int j = 0; 1455 int j = 0;
1312 int chargers_externally_control = 1;
1313 union power_supply_propval val; 1456 union power_supply_propval val;
1314 1457
1315 if (g_desc && !rtc_dev && g_desc->rtc_name) { 1458 if (g_desc && !rtc_dev && g_desc->rtc_name) {
@@ -1440,11 +1583,10 @@ static int charger_manager_probe(struct platform_device *pdev)
1440 1583
1441 memcpy(&cm->charger_psy, &psy_default, sizeof(psy_default)); 1584 memcpy(&cm->charger_psy, &psy_default, sizeof(psy_default));
1442 1585
1443 if (!desc->psy_name) { 1586 if (!desc->psy_name)
1444 strncpy(cm->psy_name_buf, psy_default.name, PSY_NAME_MAX); 1587 strncpy(cm->psy_name_buf, psy_default.name, PSY_NAME_MAX);
1445 } else { 1588 else
1446 strncpy(cm->psy_name_buf, desc->psy_name, PSY_NAME_MAX); 1589 strncpy(cm->psy_name_buf, desc->psy_name, PSY_NAME_MAX);
1447 }
1448 cm->charger_psy.name = cm->psy_name_buf; 1590 cm->charger_psy.name = cm->psy_name_buf;
1449 1591
1450 /* Allocate for psy properties because they may vary */ 1592 /* Allocate for psy properties because they may vary */
@@ -1496,105 +1638,19 @@ static int charger_manager_probe(struct platform_device *pdev)
1496 goto err_register; 1638 goto err_register;
1497 } 1639 }
1498 1640
1499 for (i = 0 ; i < desc->num_charger_regulators ; i++) { 1641 /* Register extcon device for charger cable */
1500 struct charger_regulator *charger 1642 ret = charger_manager_register_extcon(cm);
1501 = &desc->charger_regulators[i]; 1643 if (ret < 0) {
1502 char buf[11]; 1644 dev_err(&pdev->dev, "Cannot initialize extcon device\n");
1503 char *str; 1645 goto err_reg_extcon;
1504
1505 charger->consumer = regulator_get(&pdev->dev,
1506 charger->regulator_name);
1507 if (charger->consumer == NULL) {
1508 dev_err(&pdev->dev, "Cannot find charger(%s)n",
1509 charger->regulator_name);
1510 ret = -EINVAL;
1511 goto err_chg_get;
1512 }
1513 charger->cm = cm;
1514
1515 for (j = 0 ; j < charger->num_cables ; j++) {
1516 struct charger_cable *cable = &charger->cables[j];
1517
1518 ret = charger_extcon_init(cm, cable);
1519 if (ret < 0) {
1520 dev_err(&pdev->dev, "Cannot find charger(%s)n",
1521 charger->regulator_name);
1522 goto err_extcon;
1523 }
1524 cable->charger = charger;
1525 cable->cm = cm;
1526 }
1527
1528 /* Create sysfs entry to control charger(regulator) */
1529 snprintf(buf, 10, "charger.%d", i);
1530 str = kzalloc(sizeof(char) * (strlen(buf) + 1), GFP_KERNEL);
1531 if (!str) {
1532 for (i--; i >= 0; i--) {
1533 charger = &desc->charger_regulators[i];
1534 kfree(charger->attr_g.name);
1535 }
1536 ret = -ENOMEM;
1537
1538 goto err_extcon;
1539 }
1540 strcpy(str, buf);
1541
1542 charger->attrs[0] = &charger->attr_name.attr;
1543 charger->attrs[1] = &charger->attr_state.attr;
1544 charger->attrs[2] = &charger->attr_externally_control.attr;
1545 charger->attrs[3] = NULL;
1546 charger->attr_g.name = str;
1547 charger->attr_g.attrs = charger->attrs;
1548
1549 sysfs_attr_init(&charger->attr_name.attr);
1550 charger->attr_name.attr.name = "name";
1551 charger->attr_name.attr.mode = 0444;
1552 charger->attr_name.show = charger_name_show;
1553
1554 sysfs_attr_init(&charger->attr_state.attr);
1555 charger->attr_state.attr.name = "state";
1556 charger->attr_state.attr.mode = 0444;
1557 charger->attr_state.show = charger_state_show;
1558
1559 sysfs_attr_init(&charger->attr_externally_control.attr);
1560 charger->attr_externally_control.attr.name
1561 = "externally_control";
1562 charger->attr_externally_control.attr.mode = 0644;
1563 charger->attr_externally_control.show
1564 = charger_externally_control_show;
1565 charger->attr_externally_control.store
1566 = charger_externally_control_store;
1567
1568 if (!desc->charger_regulators[i].externally_control ||
1569 !chargers_externally_control) {
1570 chargers_externally_control = 0;
1571 }
1572 dev_info(&pdev->dev, "'%s' regulator's externally_control"
1573 "is %d\n", charger->regulator_name,
1574 charger->externally_control);
1575
1576 ret = sysfs_create_group(&cm->charger_psy.dev->kobj,
1577 &charger->attr_g);
1578 if (ret < 0) {
1579 dev_info(&pdev->dev, "Cannot create sysfs entry"
1580 "of %s regulator\n",
1581 charger->regulator_name);
1582 }
1583 }
1584
1585 if (chargers_externally_control) {
1586 dev_err(&pdev->dev, "Cannot register regulator because "
1587 "charger-manager must need at least "
1588 "one charger for charging battery\n");
1589
1590 ret = -EINVAL;
1591 goto err_chg_enable;
1592 } 1646 }
1593 1647
1594 ret = try_charger_enable(cm, true); 1648 /* Register sysfs entry for charger(regulator) */
1595 if (ret) { 1649 ret = charger_manager_register_sysfs(cm);
1596 dev_err(&pdev->dev, "Cannot enable charger regulators\n"); 1650 if (ret < 0) {
1597 goto err_chg_enable; 1651 dev_err(&pdev->dev,
1652 "Cannot initialize sysfs entry of regulator\n");
1653 goto err_reg_sysfs;
1598 } 1654 }
1599 1655
1600 /* Add to the list */ 1656 /* Add to the list */
@@ -1613,27 +1669,28 @@ static int charger_manager_probe(struct platform_device *pdev)
1613 1669
1614 return 0; 1670 return 0;
1615 1671
1616err_chg_enable: 1672err_reg_sysfs:
1617 for (i = 0; i < desc->num_charger_regulators; i++) { 1673 for (i = 0; i < desc->num_charger_regulators; i++) {
1618 struct charger_regulator *charger; 1674 struct charger_regulator *charger;
1619 1675
1620 charger = &desc->charger_regulators[i]; 1676 charger = &desc->charger_regulators[i];
1621 sysfs_remove_group(&cm->charger_psy.dev->kobj, 1677 sysfs_remove_group(&cm->charger_psy.dev->kobj,
1622 &charger->attr_g); 1678 &charger->attr_g);
1679
1623 kfree(charger->attr_g.name); 1680 kfree(charger->attr_g.name);
1624 } 1681 }
1625err_extcon: 1682err_reg_extcon:
1626 for (i = 0 ; i < desc->num_charger_regulators ; i++) { 1683 for (i = 0; i < desc->num_charger_regulators; i++) {
1627 struct charger_regulator *charger 1684 struct charger_regulator *charger;
1628 = &desc->charger_regulators[i]; 1685
1629 for (j = 0 ; j < charger->num_cables ; j++) { 1686 charger = &desc->charger_regulators[i];
1687 for (j = 0; j < charger->num_cables; j++) {
1630 struct charger_cable *cable = &charger->cables[j]; 1688 struct charger_cable *cable = &charger->cables[j];
1631 extcon_unregister_interest(&cable->extcon_dev); 1689 extcon_unregister_interest(&cable->extcon_dev);
1632 } 1690 }
1633 } 1691
1634err_chg_get:
1635 for (i = 0 ; i < desc->num_charger_regulators ; i++)
1636 regulator_put(desc->charger_regulators[i].consumer); 1692 regulator_put(desc->charger_regulators[i].consumer);
1693 }
1637 1694
1638 power_supply_unregister(&cm->charger_psy); 1695 power_supply_unregister(&cm->charger_psy);
1639err_register: 1696err_register: