| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * bq2415x charger driver |
|---|
| 3 | 4 | * |
|---|
| 4 | | - * Copyright (C) 2011-2013 Pali Rohár <pali.rohar@gmail.com> |
|---|
| 5 | | - * |
|---|
| 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 |
|---|
| 8 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 9 | | - * (at your option) any later version. |
|---|
| 10 | | - * |
|---|
| 11 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 12 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 13 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 14 | | - * GNU General Public License for more details. |
|---|
| 5 | + * Copyright (C) 2011-2013 Pali Rohár <pali@kernel.org> |
|---|
| 15 | 6 | * |
|---|
| 16 | 7 | * Datasheets: |
|---|
| 17 | | - * http://www.ti.com/product/bq24150 |
|---|
| 18 | | - * http://www.ti.com/product/bq24150a |
|---|
| 19 | | - * http://www.ti.com/product/bq24152 |
|---|
| 20 | | - * http://www.ti.com/product/bq24153 |
|---|
| 21 | | - * http://www.ti.com/product/bq24153a |
|---|
| 22 | | - * http://www.ti.com/product/bq24155 |
|---|
| 23 | | - * http://www.ti.com/product/bq24157s |
|---|
| 24 | | - * http://www.ti.com/product/bq24158 |
|---|
| 8 | + * https://www.ti.com/product/bq24150 |
|---|
| 9 | + * https://www.ti.com/product/bq24150a |
|---|
| 10 | + * https://www.ti.com/product/bq24152 |
|---|
| 11 | + * https://www.ti.com/product/bq24153 |
|---|
| 12 | + * https://www.ti.com/product/bq24153a |
|---|
| 13 | + * https://www.ti.com/product/bq24155 |
|---|
| 14 | + * https://www.ti.com/product/bq24157s |
|---|
| 15 | + * https://www.ti.com/product/bq24158 |
|---|
| 25 | 16 | */ |
|---|
| 26 | 17 | |
|---|
| 27 | 18 | #include <linux/kernel.h> |
|---|
| .. | .. |
|---|
| 1032 | 1023 | return 0; |
|---|
| 1033 | 1024 | } |
|---|
| 1034 | 1025 | |
|---|
| 1035 | | -static int bq2415x_power_supply_init(struct bq2415x_device *bq) |
|---|
| 1036 | | -{ |
|---|
| 1037 | | - int ret; |
|---|
| 1038 | | - int chip; |
|---|
| 1039 | | - char revstr[8]; |
|---|
| 1040 | | - struct power_supply_config psy_cfg = { |
|---|
| 1041 | | - .drv_data = bq, |
|---|
| 1042 | | - .of_node = bq->dev->of_node, |
|---|
| 1043 | | - }; |
|---|
| 1044 | | - |
|---|
| 1045 | | - bq->charger_desc.name = bq->name; |
|---|
| 1046 | | - bq->charger_desc.type = POWER_SUPPLY_TYPE_USB; |
|---|
| 1047 | | - bq->charger_desc.properties = bq2415x_power_supply_props; |
|---|
| 1048 | | - bq->charger_desc.num_properties = |
|---|
| 1049 | | - ARRAY_SIZE(bq2415x_power_supply_props); |
|---|
| 1050 | | - bq->charger_desc.get_property = bq2415x_power_supply_get_property; |
|---|
| 1051 | | - |
|---|
| 1052 | | - ret = bq2415x_detect_chip(bq); |
|---|
| 1053 | | - if (ret < 0) |
|---|
| 1054 | | - chip = BQUNKNOWN; |
|---|
| 1055 | | - else |
|---|
| 1056 | | - chip = ret; |
|---|
| 1057 | | - |
|---|
| 1058 | | - ret = bq2415x_detect_revision(bq); |
|---|
| 1059 | | - if (ret < 0) |
|---|
| 1060 | | - strcpy(revstr, "unknown"); |
|---|
| 1061 | | - else |
|---|
| 1062 | | - sprintf(revstr, "1.%d", ret); |
|---|
| 1063 | | - |
|---|
| 1064 | | - bq->model = kasprintf(GFP_KERNEL, |
|---|
| 1065 | | - "chip %s, revision %s, vender code %.3d", |
|---|
| 1066 | | - bq2415x_chip_name[chip], revstr, |
|---|
| 1067 | | - bq2415x_get_vender_code(bq)); |
|---|
| 1068 | | - if (!bq->model) { |
|---|
| 1069 | | - dev_err(bq->dev, "failed to allocate model name\n"); |
|---|
| 1070 | | - return -ENOMEM; |
|---|
| 1071 | | - } |
|---|
| 1072 | | - |
|---|
| 1073 | | - bq->charger = power_supply_register(bq->dev, &bq->charger_desc, |
|---|
| 1074 | | - &psy_cfg); |
|---|
| 1075 | | - if (IS_ERR(bq->charger)) { |
|---|
| 1076 | | - kfree(bq->model); |
|---|
| 1077 | | - return PTR_ERR(bq->charger); |
|---|
| 1078 | | - } |
|---|
| 1079 | | - |
|---|
| 1080 | | - return 0; |
|---|
| 1081 | | -} |
|---|
| 1082 | | - |
|---|
| 1083 | 1026 | static void bq2415x_power_supply_exit(struct bq2415x_device *bq) |
|---|
| 1084 | 1027 | { |
|---|
| 1085 | 1028 | bq->autotimer = 0; |
|---|
| .. | .. |
|---|
| 1496 | 1439 | static DEVICE_ATTR(boost_status, S_IRUGO, bq2415x_sysfs_show_status, NULL); |
|---|
| 1497 | 1440 | static DEVICE_ATTR(fault_status, S_IRUGO, bq2415x_sysfs_show_status, NULL); |
|---|
| 1498 | 1441 | |
|---|
| 1499 | | -static struct attribute *bq2415x_sysfs_attributes[] = { |
|---|
| 1442 | +static struct attribute *bq2415x_sysfs_attrs[] = { |
|---|
| 1500 | 1443 | /* |
|---|
| 1501 | 1444 | * TODO: some (appropriate) of these attrs should be switched to |
|---|
| 1502 | 1445 | * use power supply class props. |
|---|
| .. | .. |
|---|
| 1525 | 1468 | NULL, |
|---|
| 1526 | 1469 | }; |
|---|
| 1527 | 1470 | |
|---|
| 1528 | | -static const struct attribute_group bq2415x_sysfs_attr_group = { |
|---|
| 1529 | | - .attrs = bq2415x_sysfs_attributes, |
|---|
| 1530 | | -}; |
|---|
| 1471 | +ATTRIBUTE_GROUPS(bq2415x_sysfs); |
|---|
| 1531 | 1472 | |
|---|
| 1532 | | -static int bq2415x_sysfs_init(struct bq2415x_device *bq) |
|---|
| 1473 | +static int bq2415x_power_supply_init(struct bq2415x_device *bq) |
|---|
| 1533 | 1474 | { |
|---|
| 1534 | | - return sysfs_create_group(&bq->charger->dev.kobj, |
|---|
| 1535 | | - &bq2415x_sysfs_attr_group); |
|---|
| 1536 | | -} |
|---|
| 1475 | + int ret; |
|---|
| 1476 | + int chip; |
|---|
| 1477 | + char revstr[8]; |
|---|
| 1478 | + struct power_supply_config psy_cfg = { |
|---|
| 1479 | + .drv_data = bq, |
|---|
| 1480 | + .of_node = bq->dev->of_node, |
|---|
| 1481 | + .attr_grp = bq2415x_sysfs_groups, |
|---|
| 1482 | + }; |
|---|
| 1537 | 1483 | |
|---|
| 1538 | | -static void bq2415x_sysfs_exit(struct bq2415x_device *bq) |
|---|
| 1539 | | -{ |
|---|
| 1540 | | - sysfs_remove_group(&bq->charger->dev.kobj, &bq2415x_sysfs_attr_group); |
|---|
| 1484 | + bq->charger_desc.name = bq->name; |
|---|
| 1485 | + bq->charger_desc.type = POWER_SUPPLY_TYPE_USB; |
|---|
| 1486 | + bq->charger_desc.properties = bq2415x_power_supply_props; |
|---|
| 1487 | + bq->charger_desc.num_properties = |
|---|
| 1488 | + ARRAY_SIZE(bq2415x_power_supply_props); |
|---|
| 1489 | + bq->charger_desc.get_property = bq2415x_power_supply_get_property; |
|---|
| 1490 | + |
|---|
| 1491 | + ret = bq2415x_detect_chip(bq); |
|---|
| 1492 | + if (ret < 0) |
|---|
| 1493 | + chip = BQUNKNOWN; |
|---|
| 1494 | + else |
|---|
| 1495 | + chip = ret; |
|---|
| 1496 | + |
|---|
| 1497 | + ret = bq2415x_detect_revision(bq); |
|---|
| 1498 | + if (ret < 0) |
|---|
| 1499 | + strcpy(revstr, "unknown"); |
|---|
| 1500 | + else |
|---|
| 1501 | + sprintf(revstr, "1.%d", ret); |
|---|
| 1502 | + |
|---|
| 1503 | + bq->model = kasprintf(GFP_KERNEL, |
|---|
| 1504 | + "chip %s, revision %s, vender code %.3d", |
|---|
| 1505 | + bq2415x_chip_name[chip], revstr, |
|---|
| 1506 | + bq2415x_get_vender_code(bq)); |
|---|
| 1507 | + if (!bq->model) { |
|---|
| 1508 | + dev_err(bq->dev, "failed to allocate model name\n"); |
|---|
| 1509 | + return -ENOMEM; |
|---|
| 1510 | + } |
|---|
| 1511 | + |
|---|
| 1512 | + bq->charger = power_supply_register(bq->dev, &bq->charger_desc, |
|---|
| 1513 | + &psy_cfg); |
|---|
| 1514 | + if (IS_ERR(bq->charger)) { |
|---|
| 1515 | + kfree(bq->model); |
|---|
| 1516 | + return PTR_ERR(bq->charger); |
|---|
| 1517 | + } |
|---|
| 1518 | + |
|---|
| 1519 | + return 0; |
|---|
| 1541 | 1520 | } |
|---|
| 1542 | 1521 | |
|---|
| 1543 | 1522 | /* main bq2415x probe function */ |
|---|
| .. | .. |
|---|
| 1651 | 1630 | goto error_2; |
|---|
| 1652 | 1631 | } |
|---|
| 1653 | 1632 | |
|---|
| 1654 | | - ret = bq2415x_sysfs_init(bq); |
|---|
| 1655 | | - if (ret) { |
|---|
| 1656 | | - dev_err(bq->dev, "failed to create sysfs entries: %d\n", ret); |
|---|
| 1657 | | - goto error_3; |
|---|
| 1658 | | - } |
|---|
| 1659 | | - |
|---|
| 1660 | 1633 | ret = bq2415x_set_defaults(bq); |
|---|
| 1661 | 1634 | if (ret) { |
|---|
| 1662 | 1635 | dev_err(bq->dev, "failed to set default values: %d\n", ret); |
|---|
| 1663 | | - goto error_4; |
|---|
| 1636 | + goto error_3; |
|---|
| 1664 | 1637 | } |
|---|
| 1665 | 1638 | |
|---|
| 1666 | 1639 | if (bq->notify_node || bq->init_data.notify_device) { |
|---|
| .. | .. |
|---|
| 1668 | 1641 | ret = power_supply_reg_notifier(&bq->nb); |
|---|
| 1669 | 1642 | if (ret) { |
|---|
| 1670 | 1643 | dev_err(bq->dev, "failed to reg notifier: %d\n", ret); |
|---|
| 1671 | | - goto error_4; |
|---|
| 1644 | + goto error_3; |
|---|
| 1672 | 1645 | } |
|---|
| 1673 | 1646 | |
|---|
| 1674 | 1647 | bq->automode = 1; |
|---|
| .. | .. |
|---|
| 1707 | 1680 | dev_info(bq->dev, "driver registered\n"); |
|---|
| 1708 | 1681 | return 0; |
|---|
| 1709 | 1682 | |
|---|
| 1710 | | -error_4: |
|---|
| 1711 | | - bq2415x_sysfs_exit(bq); |
|---|
| 1712 | 1683 | error_3: |
|---|
| 1713 | 1684 | bq2415x_power_supply_exit(bq); |
|---|
| 1714 | 1685 | error_2: |
|---|
| .. | .. |
|---|
| 1733 | 1704 | power_supply_unreg_notifier(&bq->nb); |
|---|
| 1734 | 1705 | |
|---|
| 1735 | 1706 | of_node_put(bq->notify_node); |
|---|
| 1736 | | - bq2415x_sysfs_exit(bq); |
|---|
| 1737 | 1707 | bq2415x_power_supply_exit(bq); |
|---|
| 1738 | 1708 | |
|---|
| 1739 | 1709 | bq2415x_reset_chip(bq); |
|---|
| .. | .. |
|---|
| 1818 | 1788 | }; |
|---|
| 1819 | 1789 | module_i2c_driver(bq2415x_driver); |
|---|
| 1820 | 1790 | |
|---|
| 1821 | | -MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>"); |
|---|
| 1791 | +MODULE_AUTHOR("Pali Rohár <pali@kernel.org>"); |
|---|
| 1822 | 1792 | MODULE_DESCRIPTION("bq2415x charger driver"); |
|---|
| 1823 | 1793 | MODULE_LICENSE("GPL"); |
|---|