Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Battery charger driver for TI's tps65090
0004  *
0005  * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
0006 
0007  */
0008 #include <linux/delay.h>
0009 #include <linux/err.h>
0010 #include <linux/freezer.h>
0011 #include <linux/init.h>
0012 #include <linux/interrupt.h>
0013 #include <linux/kernel.h>
0014 #include <linux/kthread.h>
0015 #include <linux/module.h>
0016 #include <linux/of_device.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/power_supply.h>
0019 #include <linux/slab.h>
0020 
0021 #include <linux/mfd/tps65090.h>
0022 
0023 #define TPS65090_CHARGER_ENABLE BIT(0)
0024 #define TPS65090_VACG       BIT(1)
0025 #define TPS65090_NOITERM    BIT(5)
0026 
0027 #define POLL_INTERVAL       (HZ * 2)    /* Used when no irq */
0028 
0029 struct tps65090_charger {
0030     struct  device  *dev;
0031     int ac_online;
0032     int prev_ac_online;
0033     int irq;
0034     struct task_struct  *poll_task;
0035     bool            passive_mode;
0036     struct power_supply *ac;
0037     struct tps65090_platform_data *pdata;
0038 };
0039 
0040 static enum power_supply_property tps65090_ac_props[] = {
0041     POWER_SUPPLY_PROP_ONLINE,
0042 };
0043 
0044 static int tps65090_low_chrg_current(struct tps65090_charger *charger)
0045 {
0046     int ret;
0047 
0048     if (charger->passive_mode)
0049         return 0;
0050 
0051     ret = tps65090_write(charger->dev->parent, TPS65090_REG_CG_CTRL5,
0052             TPS65090_NOITERM);
0053     if (ret < 0) {
0054         dev_err(charger->dev, "%s(): error reading in register 0x%x\n",
0055             __func__, TPS65090_REG_CG_CTRL5);
0056         return ret;
0057     }
0058     return 0;
0059 }
0060 
0061 static int tps65090_enable_charging(struct tps65090_charger *charger)
0062 {
0063     int ret;
0064     uint8_t ctrl0 = 0;
0065 
0066     if (charger->passive_mode)
0067         return 0;
0068 
0069     ret = tps65090_read(charger->dev->parent, TPS65090_REG_CG_CTRL0,
0070                 &ctrl0);
0071     if (ret < 0) {
0072         dev_err(charger->dev, "%s(): error reading in register 0x%x\n",
0073                 __func__, TPS65090_REG_CG_CTRL0);
0074         return ret;
0075     }
0076 
0077     ret = tps65090_write(charger->dev->parent, TPS65090_REG_CG_CTRL0,
0078                 (ctrl0 | TPS65090_CHARGER_ENABLE));
0079     if (ret < 0) {
0080         dev_err(charger->dev, "%s(): error writing in register 0x%x\n",
0081                 __func__, TPS65090_REG_CG_CTRL0);
0082         return ret;
0083     }
0084     return 0;
0085 }
0086 
0087 static int tps65090_config_charger(struct tps65090_charger *charger)
0088 {
0089     uint8_t intrmask = 0;
0090     int ret;
0091 
0092     if (charger->passive_mode)
0093         return 0;
0094 
0095     if (charger->pdata->enable_low_current_chrg) {
0096         ret = tps65090_low_chrg_current(charger);
0097         if (ret < 0) {
0098             dev_err(charger->dev,
0099                 "error configuring low charge current\n");
0100             return ret;
0101         }
0102     }
0103 
0104     /* Enable the VACG interrupt for AC power detect */
0105     ret = tps65090_read(charger->dev->parent, TPS65090_REG_INTR_MASK,
0106                 &intrmask);
0107     if (ret < 0) {
0108         dev_err(charger->dev, "%s(): error reading in register 0x%x\n",
0109             __func__, TPS65090_REG_INTR_MASK);
0110         return ret;
0111     }
0112 
0113     ret = tps65090_write(charger->dev->parent, TPS65090_REG_INTR_MASK,
0114                  (intrmask | TPS65090_VACG));
0115     if (ret < 0) {
0116         dev_err(charger->dev, "%s(): error writing in register 0x%x\n",
0117             __func__, TPS65090_REG_CG_CTRL0);
0118         return ret;
0119     }
0120 
0121     return 0;
0122 }
0123 
0124 static int tps65090_ac_get_property(struct power_supply *psy,
0125             enum power_supply_property psp,
0126             union power_supply_propval *val)
0127 {
0128     struct tps65090_charger *charger = power_supply_get_drvdata(psy);
0129 
0130     if (psp == POWER_SUPPLY_PROP_ONLINE) {
0131         val->intval = charger->ac_online;
0132         charger->prev_ac_online = charger->ac_online;
0133         return 0;
0134     }
0135     return -EINVAL;
0136 }
0137 
0138 static irqreturn_t tps65090_charger_isr(int irq, void *dev_id)
0139 {
0140     struct tps65090_charger *charger = dev_id;
0141     int ret;
0142     uint8_t status1 = 0;
0143     uint8_t intrsts = 0;
0144 
0145     ret = tps65090_read(charger->dev->parent, TPS65090_REG_CG_STATUS1,
0146                 &status1);
0147     if (ret < 0) {
0148         dev_err(charger->dev, "%s(): Error in reading reg 0x%x\n",
0149                 __func__, TPS65090_REG_CG_STATUS1);
0150         return IRQ_HANDLED;
0151     }
0152     msleep(75);
0153     ret = tps65090_read(charger->dev->parent, TPS65090_REG_INTR_STS,
0154                 &intrsts);
0155     if (ret < 0) {
0156         dev_err(charger->dev, "%s(): Error in reading reg 0x%x\n",
0157                 __func__, TPS65090_REG_INTR_STS);
0158         return IRQ_HANDLED;
0159     }
0160 
0161     if (intrsts & TPS65090_VACG) {
0162         ret = tps65090_enable_charging(charger);
0163         if (ret < 0)
0164             return IRQ_HANDLED;
0165         charger->ac_online = 1;
0166     } else {
0167         charger->ac_online = 0;
0168     }
0169 
0170     /* Clear interrupts. */
0171     if (!charger->passive_mode) {
0172         ret = tps65090_write(charger->dev->parent,
0173                      TPS65090_REG_INTR_STS, 0x00);
0174         if (ret < 0) {
0175             dev_err(charger->dev,
0176                 "%s(): Error in writing reg 0x%x\n",
0177                 __func__, TPS65090_REG_INTR_STS);
0178         }
0179     }
0180 
0181     if (charger->prev_ac_online != charger->ac_online)
0182         power_supply_changed(charger->ac);
0183 
0184     return IRQ_HANDLED;
0185 }
0186 
0187 static struct tps65090_platform_data *
0188         tps65090_parse_dt_charger_data(struct platform_device *pdev)
0189 {
0190     struct tps65090_platform_data *pdata;
0191     struct device_node *np = pdev->dev.of_node;
0192     unsigned int prop;
0193 
0194     pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
0195     if (!pdata) {
0196         dev_err(&pdev->dev, "Memory alloc for tps65090_pdata failed\n");
0197         return NULL;
0198     }
0199 
0200     prop = of_property_read_bool(np, "ti,enable-low-current-chrg");
0201     pdata->enable_low_current_chrg = prop;
0202 
0203     pdata->irq_base = -1;
0204 
0205     return pdata;
0206 
0207 }
0208 
0209 static int tps65090_charger_poll_task(void *data)
0210 {
0211     set_freezable();
0212 
0213     while (!kthread_should_stop()) {
0214         schedule_timeout_interruptible(POLL_INTERVAL);
0215         try_to_freeze();
0216         tps65090_charger_isr(-1, data);
0217     }
0218     return 0;
0219 }
0220 
0221 static const struct power_supply_desc tps65090_charger_desc = {
0222     .name           = "tps65090-ac",
0223     .type           = POWER_SUPPLY_TYPE_MAINS,
0224     .get_property       = tps65090_ac_get_property,
0225     .properties     = tps65090_ac_props,
0226     .num_properties     = ARRAY_SIZE(tps65090_ac_props),
0227 };
0228 
0229 static int tps65090_charger_probe(struct platform_device *pdev)
0230 {
0231     struct tps65090_charger *cdata;
0232     struct tps65090_platform_data *pdata;
0233     struct power_supply_config psy_cfg = {};
0234     uint8_t status1 = 0;
0235     int ret;
0236     int irq;
0237 
0238     pdata = dev_get_platdata(pdev->dev.parent);
0239 
0240     if (IS_ENABLED(CONFIG_OF) && !pdata && pdev->dev.of_node)
0241         pdata = tps65090_parse_dt_charger_data(pdev);
0242 
0243     if (!pdata) {
0244         dev_err(&pdev->dev, "%s():no platform data available\n",
0245                 __func__);
0246         return -ENODEV;
0247     }
0248 
0249     cdata = devm_kzalloc(&pdev->dev, sizeof(*cdata), GFP_KERNEL);
0250     if (!cdata) {
0251         dev_err(&pdev->dev, "failed to allocate memory status\n");
0252         return -ENOMEM;
0253     }
0254 
0255     platform_set_drvdata(pdev, cdata);
0256 
0257     cdata->dev          = &pdev->dev;
0258     cdata->pdata            = pdata;
0259 
0260     psy_cfg.supplied_to     = pdata->supplied_to;
0261     psy_cfg.num_supplicants     = pdata->num_supplicants;
0262     psy_cfg.of_node         = pdev->dev.of_node;
0263     psy_cfg.drv_data        = cdata;
0264 
0265     cdata->ac = power_supply_register(&pdev->dev, &tps65090_charger_desc,
0266             &psy_cfg);
0267     if (IS_ERR(cdata->ac)) {
0268         dev_err(&pdev->dev, "failed: power supply register\n");
0269         return PTR_ERR(cdata->ac);
0270     }
0271 
0272     irq = platform_get_irq(pdev, 0);
0273     if (irq < 0)
0274         irq = -ENXIO;
0275     cdata->irq = irq;
0276 
0277     ret = tps65090_config_charger(cdata);
0278     if (ret < 0) {
0279         dev_err(&pdev->dev, "charger config failed, err %d\n", ret);
0280         goto fail_unregister_supply;
0281     }
0282 
0283     /* Check for charger presence */
0284     ret = tps65090_read(cdata->dev->parent, TPS65090_REG_CG_STATUS1,
0285             &status1);
0286     if (ret < 0) {
0287         dev_err(cdata->dev, "%s(): Error in reading reg 0x%x", __func__,
0288             TPS65090_REG_CG_STATUS1);
0289         goto fail_unregister_supply;
0290     }
0291 
0292     if (status1 != 0) {
0293         ret = tps65090_enable_charging(cdata);
0294         if (ret < 0) {
0295             dev_err(cdata->dev, "error enabling charger\n");
0296             goto fail_unregister_supply;
0297         }
0298         cdata->ac_online = 1;
0299         power_supply_changed(cdata->ac);
0300     }
0301 
0302     if (irq != -ENXIO) {
0303         ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
0304             tps65090_charger_isr, IRQF_ONESHOT, "tps65090-charger", cdata);
0305         if (ret) {
0306             dev_err(cdata->dev,
0307                 "Unable to register irq %d err %d\n", irq,
0308                 ret);
0309             goto fail_unregister_supply;
0310         }
0311     } else {
0312         cdata->poll_task = kthread_run(tps65090_charger_poll_task,
0313                           cdata, "ktps65090charger");
0314         cdata->passive_mode = true;
0315         if (IS_ERR(cdata->poll_task)) {
0316             ret = PTR_ERR(cdata->poll_task);
0317             dev_err(cdata->dev,
0318                 "Unable to run kthread err %d\n", ret);
0319             goto fail_unregister_supply;
0320         }
0321     }
0322 
0323     return 0;
0324 
0325 fail_unregister_supply:
0326     power_supply_unregister(cdata->ac);
0327 
0328     return ret;
0329 }
0330 
0331 static int tps65090_charger_remove(struct platform_device *pdev)
0332 {
0333     struct tps65090_charger *cdata = platform_get_drvdata(pdev);
0334 
0335     if (cdata->irq == -ENXIO)
0336         kthread_stop(cdata->poll_task);
0337     power_supply_unregister(cdata->ac);
0338 
0339     return 0;
0340 }
0341 
0342 static const struct of_device_id of_tps65090_charger_match[] = {
0343     { .compatible = "ti,tps65090-charger", },
0344     { /* end */ }
0345 };
0346 MODULE_DEVICE_TABLE(of, of_tps65090_charger_match);
0347 
0348 static struct platform_driver tps65090_charger_driver = {
0349     .driver = {
0350         .name   = "tps65090-charger",
0351         .of_match_table = of_tps65090_charger_match,
0352     },
0353     .probe  = tps65090_charger_probe,
0354     .remove = tps65090_charger_remove,
0355 };
0356 module_platform_driver(tps65090_charger_driver);
0357 
0358 MODULE_LICENSE("GPL v2");
0359 MODULE_AUTHOR("Syed Rafiuddin <srafiuddin@nvidia.com>");
0360 MODULE_DESCRIPTION("tps65090 battery charger driver");