linux/drivers/power/supply/bq24735-charger.c
<<
>>
Prefs
   1/*
   2 * Battery charger driver for TI BQ24735
   3 *
   4 * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
   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;
   9 *
  10 * This program is distributed in the hope that it will be useful, but WITHOUT
  11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  13 * more details.
  14 *
  15 * You should have received a copy of the GNU General Public License along
  16 * with this program; if not, write to the Free Software Foundation, Inc.,
  17 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  18 */
  19
  20#include <linux/devm-helpers.h>
  21#include <linux/err.h>
  22#include <linux/i2c.h>
  23#include <linux/init.h>
  24#include <linux/interrupt.h>
  25#include <linux/kernel.h>
  26#include <linux/module.h>
  27#include <linux/of.h>
  28#include <linux/gpio/consumer.h>
  29#include <linux/power_supply.h>
  30#include <linux/slab.h>
  31
  32#include <linux/power/bq24735-charger.h>
  33
  34/* BQ24735 available commands and their respective masks */
  35#define BQ24735_CHARGE_OPT              0x12
  36#define BQ24735_CHARGE_CURRENT          0x14
  37#define BQ24735_CHARGE_CURRENT_MASK     0x1fc0
  38#define BQ24735_CHARGE_VOLTAGE          0x15
  39#define BQ24735_CHARGE_VOLTAGE_MASK     0x7ff0
  40#define BQ24735_INPUT_CURRENT           0x3f
  41#define BQ24735_INPUT_CURRENT_MASK      0x1f80
  42#define BQ24735_MANUFACTURER_ID         0xfe
  43#define BQ24735_DEVICE_ID               0xff
  44
  45/* ChargeOptions bits of interest */
  46#define BQ24735_CHARGE_OPT_CHG_DISABLE  (1 << 0)
  47#define BQ24735_CHARGE_OPT_AC_PRESENT   (1 << 4)
  48
  49struct bq24735 {
  50        struct power_supply             *charger;
  51        struct power_supply_desc        charger_desc;
  52        struct i2c_client               *client;
  53        struct bq24735_platform         *pdata;
  54        struct mutex                    lock;
  55        struct gpio_desc                *status_gpio;
  56        struct delayed_work             poll;
  57        u32                             poll_interval;
  58        bool                            charging;
  59};
  60
  61static inline struct bq24735 *to_bq24735(struct power_supply *psy)
  62{
  63        return power_supply_get_drvdata(psy);
  64}
  65
  66static enum power_supply_property bq24735_charger_properties[] = {
  67        POWER_SUPPLY_PROP_STATUS,
  68        POWER_SUPPLY_PROP_ONLINE,
  69};
  70
  71static int bq24735_charger_property_is_writeable(struct power_supply *psy,
  72                                                 enum power_supply_property psp)
  73{
  74        switch (psp) {
  75        case POWER_SUPPLY_PROP_STATUS:
  76                return 1;
  77        default:
  78                break;
  79        }
  80
  81        return 0;
  82}
  83
  84static inline int bq24735_write_word(struct i2c_client *client, u8 reg,
  85                                     u16 value)
  86{
  87        return i2c_smbus_write_word_data(client, reg, value);
  88}
  89
  90static inline int bq24735_read_word(struct i2c_client *client, u8 reg)
  91{
  92        return i2c_smbus_read_word_data(client, reg);
  93}
  94
  95static int bq24735_update_word(struct i2c_client *client, u8 reg,
  96                               u16 mask, u16 value)
  97{
  98        unsigned int tmp;
  99        int ret;
 100
 101        ret = bq24735_read_word(client, reg);
 102        if (ret < 0)
 103                return ret;
 104
 105        tmp = ret & ~mask;
 106        tmp |= value & mask;
 107
 108        return bq24735_write_word(client, reg, tmp);
 109}
 110
 111static int bq24735_config_charger(struct bq24735 *charger)
 112{
 113        struct bq24735_platform *pdata = charger->pdata;
 114        int ret;
 115        u16 value;
 116
 117        if (pdata->ext_control)
 118                return 0;
 119
 120        if (pdata->charge_current) {
 121                value = pdata->charge_current & BQ24735_CHARGE_CURRENT_MASK;
 122
 123                ret = bq24735_write_word(charger->client,
 124                                         BQ24735_CHARGE_CURRENT, value);
 125                if (ret < 0) {
 126                        dev_err(&charger->client->dev,
 127                                "Failed to write charger current : %d\n",
 128                                ret);
 129                        return ret;
 130                }
 131        }
 132
 133        if (pdata->charge_voltage) {
 134                value = pdata->charge_voltage & BQ24735_CHARGE_VOLTAGE_MASK;
 135
 136                ret = bq24735_write_word(charger->client,
 137                                         BQ24735_CHARGE_VOLTAGE, value);
 138                if (ret < 0) {
 139                        dev_err(&charger->client->dev,
 140                                "Failed to write charger voltage : %d\n",
 141                                ret);
 142                        return ret;
 143                }
 144        }
 145
 146        if (pdata->input_current) {
 147                value = pdata->input_current & BQ24735_INPUT_CURRENT_MASK;
 148
 149                ret = bq24735_write_word(charger->client,
 150                                         BQ24735_INPUT_CURRENT, value);
 151                if (ret < 0) {
 152                        dev_err(&charger->client->dev,
 153                                "Failed to write input current : %d\n",
 154                                ret);
 155                        return ret;
 156                }
 157        }
 158
 159        return 0;
 160}
 161
 162static inline int bq24735_enable_charging(struct bq24735 *charger)
 163{
 164        int ret;
 165
 166        if (charger->pdata->ext_control)
 167                return 0;
 168
 169        ret = bq24735_config_charger(charger);
 170        if (ret)
 171                return ret;
 172
 173        return bq24735_update_word(charger->client, BQ24735_CHARGE_OPT,
 174                                   BQ24735_CHARGE_OPT_CHG_DISABLE, 0);
 175}
 176
 177static inline int bq24735_disable_charging(struct bq24735 *charger)
 178{
 179        if (charger->pdata->ext_control)
 180                return 0;
 181
 182        return bq24735_update_word(charger->client, BQ24735_CHARGE_OPT,
 183                                   BQ24735_CHARGE_OPT_CHG_DISABLE,
 184                                   BQ24735_CHARGE_OPT_CHG_DISABLE);
 185}
 186
 187static bool bq24735_charger_is_present(struct bq24735 *charger)
 188{
 189        if (charger->status_gpio) {
 190                return !gpiod_get_value_cansleep(charger->status_gpio);
 191        } else {
 192                int ac = 0;
 193
 194                ac = bq24735_read_word(charger->client, BQ24735_CHARGE_OPT);
 195                if (ac < 0) {
 196                        dev_dbg(&charger->client->dev,
 197                                "Failed to read charger options : %d\n",
 198                                ac);
 199                        return false;
 200                }
 201                return (ac & BQ24735_CHARGE_OPT_AC_PRESENT) ? true : false;
 202        }
 203
 204        return false;
 205}
 206
 207static int bq24735_charger_is_charging(struct bq24735 *charger)
 208{
 209        int ret;
 210
 211        if (!bq24735_charger_is_present(charger))
 212                return 0;
 213
 214        ret  = bq24735_read_word(charger->client, BQ24735_CHARGE_OPT);
 215        if (ret < 0)
 216                return ret;
 217
 218        return !(ret & BQ24735_CHARGE_OPT_CHG_DISABLE);
 219}
 220
 221static void bq24735_update(struct bq24735 *charger)
 222{
 223        mutex_lock(&charger->lock);
 224
 225        if (charger->charging && bq24735_charger_is_present(charger))
 226                bq24735_enable_charging(charger);
 227        else
 228                bq24735_disable_charging(charger);
 229
 230        mutex_unlock(&charger->lock);
 231
 232        power_supply_changed(charger->charger);
 233}
 234
 235static irqreturn_t bq24735_charger_isr(int irq, void *devid)
 236{
 237        struct power_supply *psy = devid;
 238        struct bq24735 *charger = to_bq24735(psy);
 239
 240        bq24735_update(charger);
 241
 242        return IRQ_HANDLED;
 243}
 244
 245static void bq24735_poll(struct work_struct *work)
 246{
 247        struct bq24735 *charger = container_of(work, struct bq24735, poll.work);
 248
 249        bq24735_update(charger);
 250
 251        schedule_delayed_work(&charger->poll,
 252                              msecs_to_jiffies(charger->poll_interval));
 253}
 254
 255static int bq24735_charger_get_property(struct power_supply *psy,
 256                                        enum power_supply_property psp,
 257                                        union power_supply_propval *val)
 258{
 259        struct bq24735 *charger = to_bq24735(psy);
 260
 261        switch (psp) {
 262        case POWER_SUPPLY_PROP_ONLINE:
 263                val->intval = bq24735_charger_is_present(charger) ? 1 : 0;
 264                break;
 265        case POWER_SUPPLY_PROP_STATUS:
 266                switch (bq24735_charger_is_charging(charger)) {
 267                case 1:
 268                        val->intval = POWER_SUPPLY_STATUS_CHARGING;
 269                        break;
 270                case 0:
 271                        val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
 272                        break;
 273                default:
 274                        val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
 275                        break;
 276                }
 277                break;
 278        default:
 279                return -EINVAL;
 280        }
 281
 282        return 0;
 283}
 284
 285static int bq24735_charger_set_property(struct power_supply *psy,
 286                                        enum power_supply_property psp,
 287                                        const union power_supply_propval *val)
 288{
 289        struct bq24735 *charger = to_bq24735(psy);
 290        int ret;
 291
 292        switch (psp) {
 293        case POWER_SUPPLY_PROP_STATUS:
 294                switch (val->intval) {
 295                case POWER_SUPPLY_STATUS_CHARGING:
 296                        mutex_lock(&charger->lock);
 297                        charger->charging = true;
 298                        ret = bq24735_enable_charging(charger);
 299                        mutex_unlock(&charger->lock);
 300                        if (ret)
 301                                return ret;
 302                        break;
 303                case POWER_SUPPLY_STATUS_DISCHARGING:
 304                case POWER_SUPPLY_STATUS_NOT_CHARGING:
 305                        mutex_lock(&charger->lock);
 306                        charger->charging = false;
 307                        ret = bq24735_disable_charging(charger);
 308                        mutex_unlock(&charger->lock);
 309                        if (ret)
 310                                return ret;
 311                        break;
 312                default:
 313                        return -EINVAL;
 314                }
 315                power_supply_changed(psy);
 316                break;
 317        default:
 318                return -EPERM;
 319        }
 320
 321        return 0;
 322}
 323
 324static struct bq24735_platform *bq24735_parse_dt_data(struct i2c_client *client)
 325{
 326        struct bq24735_platform *pdata;
 327        struct device_node *np = client->dev.of_node;
 328        u32 val;
 329        int ret;
 330
 331        pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
 332        if (!pdata) {
 333                dev_err(&client->dev,
 334                        "Memory alloc for bq24735 pdata failed\n");
 335                return NULL;
 336        }
 337
 338        ret = of_property_read_u32(np, "ti,charge-current", &val);
 339        if (!ret)
 340                pdata->charge_current = val;
 341
 342        ret = of_property_read_u32(np, "ti,charge-voltage", &val);
 343        if (!ret)
 344                pdata->charge_voltage = val;
 345
 346        ret = of_property_read_u32(np, "ti,input-current", &val);
 347        if (!ret)
 348                pdata->input_current = val;
 349
 350        pdata->ext_control = of_property_read_bool(np, "ti,external-control");
 351
 352        return pdata;
 353}
 354
 355static int bq24735_charger_probe(struct i2c_client *client,
 356                                 const struct i2c_device_id *id)
 357{
 358        int ret;
 359        struct bq24735 *charger;
 360        struct power_supply_desc *supply_desc;
 361        struct power_supply_config psy_cfg = {};
 362        char *name;
 363
 364        charger = devm_kzalloc(&client->dev, sizeof(*charger), GFP_KERNEL);
 365        if (!charger)
 366                return -ENOMEM;
 367
 368        mutex_init(&charger->lock);
 369        charger->charging = true;
 370        charger->pdata = client->dev.platform_data;
 371
 372        if (IS_ENABLED(CONFIG_OF) && !charger->pdata && client->dev.of_node)
 373                charger->pdata = bq24735_parse_dt_data(client);
 374
 375        if (!charger->pdata) {
 376                dev_err(&client->dev, "no platform data provided\n");
 377                return -EINVAL;
 378        }
 379
 380        name = (char *)charger->pdata->name;
 381        if (!name) {
 382                name = devm_kasprintf(&client->dev, GFP_KERNEL,
 383                                      "bq24735@%s",
 384                                      dev_name(&client->dev));
 385                if (!name) {
 386                        dev_err(&client->dev, "Failed to alloc device name\n");
 387                        return -ENOMEM;
 388                }
 389        }
 390
 391        charger->client = client;
 392
 393        supply_desc = &charger->charger_desc;
 394
 395        supply_desc->name = name;
 396        supply_desc->type = POWER_SUPPLY_TYPE_MAINS;
 397        supply_desc->properties = bq24735_charger_properties;
 398        supply_desc->num_properties = ARRAY_SIZE(bq24735_charger_properties);
 399        supply_desc->get_property = bq24735_charger_get_property;
 400        supply_desc->set_property = bq24735_charger_set_property;
 401        supply_desc->property_is_writeable =
 402                                bq24735_charger_property_is_writeable;
 403
 404        psy_cfg.supplied_to = charger->pdata->supplied_to;
 405        psy_cfg.num_supplicants = charger->pdata->num_supplicants;
 406        psy_cfg.of_node = client->dev.of_node;
 407        psy_cfg.drv_data = charger;
 408
 409        i2c_set_clientdata(client, charger);
 410
 411        charger->status_gpio = devm_gpiod_get_optional(&client->dev,
 412                                                       "ti,ac-detect",
 413                                                       GPIOD_IN);
 414        if (IS_ERR(charger->status_gpio)) {
 415                ret = PTR_ERR(charger->status_gpio);
 416                dev_err(&client->dev, "Getting gpio failed: %d\n", ret);
 417                return ret;
 418        }
 419
 420        if (bq24735_charger_is_present(charger)) {
 421                ret = bq24735_read_word(client, BQ24735_MANUFACTURER_ID);
 422                if (ret < 0) {
 423                        dev_err(&client->dev, "Failed to read manufacturer id : %d\n",
 424                                ret);
 425                        return ret;
 426                } else if (ret != 0x0040) {
 427                        dev_err(&client->dev,
 428                                "manufacturer id mismatch. 0x0040 != 0x%04x\n", ret);
 429                        return -ENODEV;
 430                }
 431
 432                ret = bq24735_read_word(client, BQ24735_DEVICE_ID);
 433                if (ret < 0) {
 434                        dev_err(&client->dev, "Failed to read device id : %d\n", ret);
 435                        return ret;
 436                } else if (ret != 0x000B) {
 437                        dev_err(&client->dev,
 438                                "device id mismatch. 0x000b != 0x%04x\n", ret);
 439                        return -ENODEV;
 440                }
 441
 442                ret = bq24735_enable_charging(charger);
 443                if (ret < 0) {
 444                        dev_err(&client->dev, "Failed to enable charging\n");
 445                        return ret;
 446                }
 447        }
 448
 449        charger->charger = devm_power_supply_register(&client->dev, supply_desc,
 450                                                      &psy_cfg);
 451        if (IS_ERR(charger->charger)) {
 452                ret = PTR_ERR(charger->charger);
 453                dev_err(&client->dev, "Failed to register power supply: %d\n",
 454                        ret);
 455                return ret;
 456        }
 457
 458        if (client->irq) {
 459                ret = devm_request_threaded_irq(&client->dev, client->irq,
 460                                                NULL, bq24735_charger_isr,
 461                                                IRQF_TRIGGER_RISING |
 462                                                IRQF_TRIGGER_FALLING |
 463                                                IRQF_ONESHOT,
 464                                                supply_desc->name,
 465                                                charger->charger);
 466                if (ret) {
 467                        dev_err(&client->dev,
 468                                "Unable to register IRQ %d err %d\n",
 469                                client->irq, ret);
 470                        return ret;
 471                }
 472        } else {
 473                ret = device_property_read_u32(&client->dev, "poll-interval",
 474                                               &charger->poll_interval);
 475                if (ret)
 476                        return 0;
 477                if (!charger->poll_interval)
 478                        return 0;
 479
 480                ret = devm_delayed_work_autocancel(&client->dev, &charger->poll,
 481                                                   bq24735_poll);
 482                if (ret)
 483                        return ret;
 484
 485                schedule_delayed_work(&charger->poll,
 486                                      msecs_to_jiffies(charger->poll_interval));
 487        }
 488
 489        return 0;
 490}
 491
 492static const struct i2c_device_id bq24735_charger_id[] = {
 493        { "bq24735-charger", 0 },
 494        {}
 495};
 496MODULE_DEVICE_TABLE(i2c, bq24735_charger_id);
 497
 498static const struct of_device_id bq24735_match_ids[] = {
 499        { .compatible = "ti,bq24735", },
 500        { /* end */ }
 501};
 502MODULE_DEVICE_TABLE(of, bq24735_match_ids);
 503
 504static struct i2c_driver bq24735_charger_driver = {
 505        .driver = {
 506                .name = "bq24735-charger",
 507                .of_match_table = bq24735_match_ids,
 508        },
 509        .probe = bq24735_charger_probe,
 510        .id_table = bq24735_charger_id,
 511};
 512
 513module_i2c_driver(bq24735_charger_driver);
 514
 515MODULE_DESCRIPTION("bq24735 battery charging driver");
 516MODULE_AUTHOR("Darbha Sriharsha <dsriharsha@nvidia.com>");
 517MODULE_LICENSE("GPL v2");
 518