0001
0002
0003
0004
0005
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)
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
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
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
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 { }
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");