--- zzzz-none-000/linux-3.10.107/drivers/power/tps65090-charger.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/power/tps65090-charger.c 2021-02-04 17:41:59.000000000 +0000 @@ -15,37 +15,35 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ +#include #include +#include #include #include #include +#include #include -#include -#include +#include #include #include -#include +#include -#define TPS65090_REG_INTR_STS 0x00 -#define TPS65090_REG_CG_CTRL0 0x04 -#define TPS65090_REG_CG_CTRL1 0x05 -#define TPS65090_REG_CG_CTRL2 0x06 -#define TPS65090_REG_CG_CTRL3 0x07 -#define TPS65090_REG_CG_CTRL4 0x08 -#define TPS65090_REG_CG_CTRL5 0x09 -#define TPS65090_REG_CG_STATUS1 0x0a -#define TPS65090_REG_CG_STATUS2 0x0b +#include #define TPS65090_CHARGER_ENABLE BIT(0) #define TPS65090_VACG BIT(1) #define TPS65090_NOITERM BIT(5) +#define POLL_INTERVAL (HZ * 2) /* Used when no irq */ + struct tps65090_charger { struct device *dev; int ac_online; int prev_ac_online; int irq; - struct power_supply ac; + struct task_struct *poll_task; + bool passive_mode; + struct power_supply *ac; struct tps65090_platform_data *pdata; }; @@ -57,6 +55,9 @@ { int ret; + if (charger->passive_mode) + return 0; + ret = tps65090_write(charger->dev->parent, TPS65090_REG_CG_CTRL5, TPS65090_NOITERM); if (ret < 0) { @@ -67,12 +68,14 @@ return 0; } -static int tps65090_enable_charging(struct tps65090_charger *charger, - uint8_t enable) +static int tps65090_enable_charging(struct tps65090_charger *charger) { int ret; uint8_t ctrl0 = 0; + if (charger->passive_mode) + return 0; + ret = tps65090_read(charger->dev->parent, TPS65090_REG_CG_CTRL0, &ctrl0); if (ret < 0) { @@ -84,7 +87,7 @@ ret = tps65090_write(charger->dev->parent, TPS65090_REG_CG_CTRL0, (ctrl0 | TPS65090_CHARGER_ENABLE)); if (ret < 0) { - dev_err(charger->dev, "%s(): error reading in register 0x%x\n", + dev_err(charger->dev, "%s(): error writing in register 0x%x\n", __func__, TPS65090_REG_CG_CTRL0); return ret; } @@ -93,8 +96,12 @@ static int tps65090_config_charger(struct tps65090_charger *charger) { + uint8_t intrmask = 0; int ret; + if (charger->passive_mode) + return 0; + if (charger->pdata->enable_low_current_chrg) { ret = tps65090_low_chrg_current(charger); if (ret < 0) { @@ -104,6 +111,23 @@ } } + /* Enable the VACG interrupt for AC power detect */ + ret = tps65090_read(charger->dev->parent, TPS65090_REG_INTR_MASK, + &intrmask); + if (ret < 0) { + dev_err(charger->dev, "%s(): error reading in register 0x%x\n", + __func__, TPS65090_REG_INTR_MASK); + return ret; + } + + ret = tps65090_write(charger->dev->parent, TPS65090_REG_INTR_MASK, + (intrmask | TPS65090_VACG)); + if (ret < 0) { + dev_err(charger->dev, "%s(): error writing in register 0x%x\n", + __func__, TPS65090_REG_CG_CTRL0); + return ret; + } + return 0; } @@ -111,8 +135,7 @@ enum power_supply_property psp, union power_supply_propval *val) { - struct tps65090_charger *charger = container_of(psy, - struct tps65090_charger, ac); + struct tps65090_charger *charger = power_supply_get_drvdata(psy); if (psp == POWER_SUPPLY_PROP_ONLINE) { val->intval = charger->ac_online; @@ -146,7 +169,7 @@ } if (intrsts & TPS65090_VACG) { - ret = tps65090_enable_charging(charger, 1); + ret = tps65090_enable_charging(charger); if (ret < 0) return IRQ_HANDLED; charger->ac_online = 1; @@ -154,16 +177,23 @@ charger->ac_online = 0; } + /* Clear interrupts. */ + if (!charger->passive_mode) { + ret = tps65090_write(charger->dev->parent, + TPS65090_REG_INTR_STS, 0x00); + if (ret < 0) { + dev_err(charger->dev, + "%s(): Error in writing reg 0x%x\n", + __func__, TPS65090_REG_INTR_STS); + } + } + if (charger->prev_ac_online != charger->ac_online) - power_supply_changed(&charger->ac); + power_supply_changed(charger->ac); return IRQ_HANDLED; } -#if defined(CONFIG_OF) - -#include - static struct tps65090_platform_data * tps65090_parse_dt_charger_data(struct platform_device *pdev) { @@ -185,25 +215,39 @@ return pdata; } -#else -static struct tps65090_platform_data * - tps65090_parse_dt_charger_data(struct platform_device *pdev) + +static int tps65090_charger_poll_task(void *data) { - return NULL; + set_freezable(); + + while (!kthread_should_stop()) { + schedule_timeout_interruptible(POLL_INTERVAL); + try_to_freeze(); + tps65090_charger_isr(-1, data); + } + return 0; } -#endif + +static const struct power_supply_desc tps65090_charger_desc = { + .name = "tps65090-ac", + .type = POWER_SUPPLY_TYPE_MAINS, + .get_property = tps65090_ac_get_property, + .properties = tps65090_ac_props, + .num_properties = ARRAY_SIZE(tps65090_ac_props), +}; static int tps65090_charger_probe(struct platform_device *pdev) { struct tps65090_charger *cdata; struct tps65090_platform_data *pdata; + struct power_supply_config psy_cfg = {}; uint8_t status1 = 0; int ret; int irq; pdata = dev_get_platdata(pdev->dev.parent); - if (!pdata && pdev->dev.of_node) + if (IS_ENABLED(CONFIG_OF) && !pdata && pdev->dev.of_node) pdata = tps65090_parse_dt_charger_data(pdev); if (!pdata) { @@ -218,46 +262,32 @@ return -ENOMEM; } - dev_set_drvdata(&pdev->dev, cdata); + platform_set_drvdata(pdev, cdata); cdata->dev = &pdev->dev; cdata->pdata = pdata; - cdata->ac.name = "tps65090-ac"; - cdata->ac.type = POWER_SUPPLY_TYPE_MAINS; - cdata->ac.get_property = tps65090_ac_get_property; - cdata->ac.properties = tps65090_ac_props; - cdata->ac.num_properties = ARRAY_SIZE(tps65090_ac_props); - cdata->ac.supplied_to = pdata->supplied_to; - cdata->ac.num_supplicants = pdata->num_supplicants; - - ret = power_supply_register(&pdev->dev, &cdata->ac); - if (ret) { + psy_cfg.supplied_to = pdata->supplied_to; + psy_cfg.num_supplicants = pdata->num_supplicants; + psy_cfg.of_node = pdev->dev.of_node; + psy_cfg.drv_data = cdata; + + cdata->ac = power_supply_register(&pdev->dev, &tps65090_charger_desc, + &psy_cfg); + if (IS_ERR(cdata->ac)) { dev_err(&pdev->dev, "failed: power supply register\n"); - return ret; + return PTR_ERR(cdata->ac); } irq = platform_get_irq(pdev, 0); - if (irq <= 0) { - dev_warn(&pdev->dev, "Unable to get charger irq = %d\n", irq); - ret = irq; - goto fail_unregister_supply; - } - + if (irq < 0) + irq = -ENXIO; cdata->irq = irq; - ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, - tps65090_charger_isr, 0, "tps65090-charger", cdata); - if (ret) { - dev_err(cdata->dev, "Unable to register irq %d err %d\n", irq, - ret); - goto fail_free_irq; - } - ret = tps65090_config_charger(cdata); if (ret < 0) { dev_err(&pdev->dev, "charger config failed, err %d\n", ret); - goto fail_free_irq; + goto fail_unregister_supply; } /* Check for charger presence */ @@ -266,49 +296,69 @@ if (ret < 0) { dev_err(cdata->dev, "%s(): Error in reading reg 0x%x", __func__, TPS65090_REG_CG_STATUS1); - goto fail_free_irq; + goto fail_unregister_supply; } if (status1 != 0) { - ret = tps65090_enable_charging(cdata, 1); + ret = tps65090_enable_charging(cdata); if (ret < 0) { dev_err(cdata->dev, "error enabling charger\n"); - goto fail_free_irq; + goto fail_unregister_supply; } cdata->ac_online = 1; - power_supply_changed(&cdata->ac); + power_supply_changed(cdata->ac); + } + + if (irq != -ENXIO) { + ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, + tps65090_charger_isr, 0, "tps65090-charger", cdata); + if (ret) { + dev_err(cdata->dev, + "Unable to register irq %d err %d\n", irq, + ret); + goto fail_unregister_supply; + } + } else { + cdata->poll_task = kthread_run(tps65090_charger_poll_task, + cdata, "ktps65090charger"); + cdata->passive_mode = true; + if (IS_ERR(cdata->poll_task)) { + ret = PTR_ERR(cdata->poll_task); + dev_err(cdata->dev, + "Unable to run kthread err %d\n", ret); + goto fail_unregister_supply; + } } return 0; -fail_free_irq: - devm_free_irq(cdata->dev, irq, cdata); fail_unregister_supply: - power_supply_unregister(&cdata->ac); + power_supply_unregister(cdata->ac); return ret; } static int tps65090_charger_remove(struct platform_device *pdev) { - struct tps65090_charger *cdata = dev_get_drvdata(&pdev->dev); + struct tps65090_charger *cdata = platform_get_drvdata(pdev); - devm_free_irq(cdata->dev, cdata->irq, cdata); - power_supply_unregister(&cdata->ac); + if (cdata->irq == -ENXIO) + kthread_stop(cdata->poll_task); + power_supply_unregister(cdata->ac); return 0; } -static struct of_device_id of_tps65090_charger_match[] = { +static const struct of_device_id of_tps65090_charger_match[] = { { .compatible = "ti,tps65090-charger", }, { /* end */ } }; +MODULE_DEVICE_TABLE(of, of_tps65090_charger_match); static struct platform_driver tps65090_charger_driver = { .driver = { .name = "tps65090-charger", .of_match_table = of_tps65090_charger_match, - .owner = THIS_MODULE, }, .probe = tps65090_charger_probe, .remove = tps65090_charger_remove,