Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  *  Driver for Analog Devices (Linear Technology) LT3651 charger IC.
0004  *  Copyright (C) 2017, Topic Embedded Products
0005  */
0006 
0007 #include <linux/device.h>
0008 #include <linux/gpio/consumer.h>
0009 #include <linux/init.h>
0010 #include <linux/interrupt.h>
0011 #include <linux/kernel.h>
0012 #include <linux/module.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/power_supply.h>
0015 #include <linux/slab.h>
0016 #include <linux/of.h>
0017 
0018 struct lt3651_charger {
0019     struct power_supply *charger;
0020     struct power_supply_desc charger_desc;
0021     struct gpio_desc *acpr_gpio;
0022     struct gpio_desc *fault_gpio;
0023     struct gpio_desc *chrg_gpio;
0024 };
0025 
0026 static irqreturn_t lt3651_charger_irq(int irq, void *devid)
0027 {
0028     struct power_supply *charger = devid;
0029 
0030     power_supply_changed(charger);
0031 
0032     return IRQ_HANDLED;
0033 }
0034 
0035 static inline struct lt3651_charger *psy_to_lt3651_charger(
0036     struct power_supply *psy)
0037 {
0038     return power_supply_get_drvdata(psy);
0039 }
0040 
0041 static int lt3651_charger_get_property(struct power_supply *psy,
0042         enum power_supply_property psp, union power_supply_propval *val)
0043 {
0044     struct lt3651_charger *lt3651_charger = psy_to_lt3651_charger(psy);
0045 
0046     switch (psp) {
0047     case POWER_SUPPLY_PROP_STATUS:
0048         if (!lt3651_charger->chrg_gpio) {
0049             val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
0050             break;
0051         }
0052         if (gpiod_get_value(lt3651_charger->chrg_gpio))
0053             val->intval = POWER_SUPPLY_STATUS_CHARGING;
0054         else
0055             val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
0056         break;
0057     case POWER_SUPPLY_PROP_ONLINE:
0058         val->intval = gpiod_get_value(lt3651_charger->acpr_gpio);
0059         break;
0060     case POWER_SUPPLY_PROP_HEALTH:
0061         if (!lt3651_charger->fault_gpio) {
0062             val->intval = POWER_SUPPLY_HEALTH_UNKNOWN;
0063             break;
0064         }
0065         if (!gpiod_get_value(lt3651_charger->fault_gpio)) {
0066             val->intval = POWER_SUPPLY_HEALTH_GOOD;
0067             break;
0068         }
0069         /*
0070          * If the fault pin is active, the chrg pin explains the type
0071          * of failure.
0072          */
0073         if (!lt3651_charger->chrg_gpio) {
0074             val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
0075             break;
0076         }
0077         val->intval = gpiod_get_value(lt3651_charger->chrg_gpio) ?
0078                 POWER_SUPPLY_HEALTH_OVERHEAT :
0079                 POWER_SUPPLY_HEALTH_DEAD;
0080         break;
0081     default:
0082         return -EINVAL;
0083     }
0084 
0085     return 0;
0086 }
0087 
0088 static enum power_supply_property lt3651_charger_properties[] = {
0089     POWER_SUPPLY_PROP_STATUS,
0090     POWER_SUPPLY_PROP_ONLINE,
0091     POWER_SUPPLY_PROP_HEALTH,
0092 };
0093 
0094 static int lt3651_charger_probe(struct platform_device *pdev)
0095 {
0096     struct power_supply_config psy_cfg = {};
0097     struct lt3651_charger *lt3651_charger;
0098     struct power_supply_desc *charger_desc;
0099     int ret;
0100 
0101     lt3651_charger = devm_kzalloc(&pdev->dev, sizeof(*lt3651_charger),
0102                     GFP_KERNEL);
0103     if (!lt3651_charger)
0104         return -ENOMEM;
0105 
0106     lt3651_charger->acpr_gpio = devm_gpiod_get(&pdev->dev,
0107                     "lltc,acpr", GPIOD_IN);
0108     if (IS_ERR(lt3651_charger->acpr_gpio)) {
0109         ret = PTR_ERR(lt3651_charger->acpr_gpio);
0110         dev_err(&pdev->dev, "Failed to acquire acpr GPIO: %d\n", ret);
0111         return ret;
0112     }
0113     lt3651_charger->fault_gpio = devm_gpiod_get_optional(&pdev->dev,
0114                     "lltc,fault", GPIOD_IN);
0115     if (IS_ERR(lt3651_charger->fault_gpio)) {
0116         ret = PTR_ERR(lt3651_charger->fault_gpio);
0117         dev_err(&pdev->dev, "Failed to acquire fault GPIO: %d\n", ret);
0118         return ret;
0119     }
0120     lt3651_charger->chrg_gpio = devm_gpiod_get_optional(&pdev->dev,
0121                     "lltc,chrg", GPIOD_IN);
0122     if (IS_ERR(lt3651_charger->chrg_gpio)) {
0123         ret = PTR_ERR(lt3651_charger->chrg_gpio);
0124         dev_err(&pdev->dev, "Failed to acquire chrg GPIO: %d\n", ret);
0125         return ret;
0126     }
0127 
0128     charger_desc = &lt3651_charger->charger_desc;
0129     charger_desc->name = pdev->dev.of_node->name;
0130     charger_desc->type = POWER_SUPPLY_TYPE_MAINS;
0131     charger_desc->properties = lt3651_charger_properties;
0132     charger_desc->num_properties = ARRAY_SIZE(lt3651_charger_properties);
0133     charger_desc->get_property = lt3651_charger_get_property;
0134     psy_cfg.of_node = pdev->dev.of_node;
0135     psy_cfg.drv_data = lt3651_charger;
0136 
0137     lt3651_charger->charger = devm_power_supply_register(&pdev->dev,
0138                               charger_desc, &psy_cfg);
0139     if (IS_ERR(lt3651_charger->charger)) {
0140         ret = PTR_ERR(lt3651_charger->charger);
0141         dev_err(&pdev->dev, "Failed to register power supply: %d\n",
0142             ret);
0143         return ret;
0144     }
0145 
0146     /*
0147      * Acquire IRQs for the GPIO pins if possible. If the system does not
0148      * support IRQs on these pins, userspace will have to poll the sysfs
0149      * files manually.
0150      */
0151     if (lt3651_charger->acpr_gpio) {
0152         ret = gpiod_to_irq(lt3651_charger->acpr_gpio);
0153         if (ret >= 0)
0154             ret = devm_request_any_context_irq(&pdev->dev, ret,
0155                 lt3651_charger_irq,
0156                 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
0157                 dev_name(&pdev->dev), lt3651_charger->charger);
0158         if (ret < 0)
0159             dev_warn(&pdev->dev, "Failed to request acpr irq\n");
0160     }
0161     if (lt3651_charger->fault_gpio) {
0162         ret = gpiod_to_irq(lt3651_charger->fault_gpio);
0163         if (ret >= 0)
0164             ret = devm_request_any_context_irq(&pdev->dev, ret,
0165                 lt3651_charger_irq,
0166                 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
0167                 dev_name(&pdev->dev), lt3651_charger->charger);
0168         if (ret < 0)
0169             dev_warn(&pdev->dev, "Failed to request fault irq\n");
0170     }
0171     if (lt3651_charger->chrg_gpio) {
0172         ret = gpiod_to_irq(lt3651_charger->chrg_gpio);
0173         if (ret >= 0)
0174             ret = devm_request_any_context_irq(&pdev->dev, ret,
0175                 lt3651_charger_irq,
0176                 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
0177                 dev_name(&pdev->dev), lt3651_charger->charger);
0178         if (ret < 0)
0179             dev_warn(&pdev->dev, "Failed to request chrg irq\n");
0180     }
0181 
0182     platform_set_drvdata(pdev, lt3651_charger);
0183 
0184     return 0;
0185 }
0186 
0187 static const struct of_device_id lt3651_charger_match[] = {
0188     { .compatible = "lltc,ltc3651-charger" }, /* DEPRECATED */
0189     { .compatible = "lltc,lt3651-charger" },
0190     { }
0191 };
0192 MODULE_DEVICE_TABLE(of, lt3651_charger_match);
0193 
0194 static struct platform_driver lt3651_charger_driver = {
0195     .probe = lt3651_charger_probe,
0196     .driver = {
0197         .name = "lt3651-charger",
0198         .of_match_table = lt3651_charger_match,
0199     },
0200 };
0201 
0202 module_platform_driver(lt3651_charger_driver);
0203 
0204 MODULE_AUTHOR("Mike Looijmans <mike.looijmans@topic.nl>");
0205 MODULE_DESCRIPTION("Driver for LT3651 charger");
0206 MODULE_LICENSE("GPL");
0207 MODULE_ALIAS("platform:lt3651-charger");