linux/drivers/power/lp8727_charger.c
<<
>>
Prefs
   1/*
   2 * Driver for LP8727 Micro/Mini USB IC with integrated charger
   3 *
   4 *                      Copyright (C) 2011 Texas Instruments
   5 *                      Copyright (C) 2011 National Semiconductor
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 as
   9 * published by the Free Software Foundation.
  10 *
  11 */
  12
  13#include <linux/module.h>
  14#include <linux/slab.h>
  15#include <linux/interrupt.h>
  16#include <linux/i2c.h>
  17#include <linux/power_supply.h>
  18#include <linux/platform_data/lp8727.h>
  19#include <linux/of.h>
  20
  21#define LP8788_NUM_INTREGS      2
  22#define DEFAULT_DEBOUNCE_MSEC   270
  23
  24/* Registers */
  25#define LP8727_CTRL1            0x1
  26#define LP8727_CTRL2            0x2
  27#define LP8727_SWCTRL           0x3
  28#define LP8727_INT1             0x4
  29#define LP8727_INT2             0x5
  30#define LP8727_STATUS1          0x6
  31#define LP8727_STATUS2          0x7
  32#define LP8727_CHGCTRL2         0x9
  33
  34/* CTRL1 register */
  35#define LP8727_CP_EN            BIT(0)
  36#define LP8727_ADC_EN           BIT(1)
  37#define LP8727_ID200_EN         BIT(4)
  38
  39/* CTRL2 register */
  40#define LP8727_CHGDET_EN        BIT(1)
  41#define LP8727_INT_EN           BIT(6)
  42
  43/* SWCTRL register */
  44#define LP8727_SW_DM1_DM        (0x0 << 0)
  45#define LP8727_SW_DM1_HiZ       (0x7 << 0)
  46#define LP8727_SW_DP2_DP        (0x0 << 3)
  47#define LP8727_SW_DP2_HiZ       (0x7 << 3)
  48
  49/* INT1 register */
  50#define LP8727_IDNO             (0xF << 0)
  51#define LP8727_VBUS             BIT(4)
  52
  53/* STATUS1 register */
  54#define LP8727_CHGSTAT          (3 << 4)
  55#define LP8727_CHPORT           BIT(6)
  56#define LP8727_DCPORT           BIT(7)
  57#define LP8727_STAT_EOC         0x30
  58
  59/* STATUS2 register */
  60#define LP8727_TEMP_STAT        (3 << 5)
  61#define LP8727_TEMP_SHIFT       5
  62
  63/* CHGCTRL2 register */
  64#define LP8727_ICHG_SHIFT       4
  65
  66enum lp8727_dev_id {
  67        LP8727_ID_NONE,
  68        LP8727_ID_TA,
  69        LP8727_ID_DEDICATED_CHG,
  70        LP8727_ID_USB_CHG,
  71        LP8727_ID_USB_DS,
  72        LP8727_ID_MAX,
  73};
  74
  75enum lp8727_die_temp {
  76        LP8788_TEMP_75C,
  77        LP8788_TEMP_95C,
  78        LP8788_TEMP_115C,
  79        LP8788_TEMP_135C,
  80};
  81
  82struct lp8727_psy {
  83        struct power_supply ac;
  84        struct power_supply usb;
  85        struct power_supply batt;
  86};
  87
  88struct lp8727_chg {
  89        struct device *dev;
  90        struct i2c_client *client;
  91        struct mutex xfer_lock;
  92        struct lp8727_psy *psy;
  93        struct lp8727_platform_data *pdata;
  94
  95        /* Charger Data */
  96        enum lp8727_dev_id devid;
  97        struct lp8727_chg_param *chg_param;
  98
  99        /* Interrupt Handling */
 100        int irq;
 101        struct delayed_work work;
 102        unsigned long debounce_jiffies;
 103};
 104
 105static int lp8727_read_bytes(struct lp8727_chg *pchg, u8 reg, u8 *data, u8 len)
 106{
 107        s32 ret;
 108
 109        mutex_lock(&pchg->xfer_lock);
 110        ret = i2c_smbus_read_i2c_block_data(pchg->client, reg, len, data);
 111        mutex_unlock(&pchg->xfer_lock);
 112
 113        return (ret != len) ? -EIO : 0;
 114}
 115
 116static inline int lp8727_read_byte(struct lp8727_chg *pchg, u8 reg, u8 *data)
 117{
 118        return lp8727_read_bytes(pchg, reg, data, 1);
 119}
 120
 121static int lp8727_write_byte(struct lp8727_chg *pchg, u8 reg, u8 data)
 122{
 123        int ret;
 124
 125        mutex_lock(&pchg->xfer_lock);
 126        ret = i2c_smbus_write_byte_data(pchg->client, reg, data);
 127        mutex_unlock(&pchg->xfer_lock);
 128
 129        return ret;
 130}
 131
 132static bool lp8727_is_charger_attached(const char *name, int id)
 133{
 134        if (!strcmp(name, "ac"))
 135                return id == LP8727_ID_TA || id == LP8727_ID_DEDICATED_CHG;
 136        else if (!strcmp(name, "usb"))
 137                return id == LP8727_ID_USB_CHG;
 138
 139        return id >= LP8727_ID_TA && id <= LP8727_ID_USB_CHG;
 140}
 141
 142static int lp8727_init_device(struct lp8727_chg *pchg)
 143{
 144        u8 val;
 145        int ret;
 146        u8 intstat[LP8788_NUM_INTREGS];
 147
 148        /* clear interrupts */
 149        ret = lp8727_read_bytes(pchg, LP8727_INT1, intstat, LP8788_NUM_INTREGS);
 150        if (ret)
 151                return ret;
 152
 153        val = LP8727_ID200_EN | LP8727_ADC_EN | LP8727_CP_EN;
 154        ret = lp8727_write_byte(pchg, LP8727_CTRL1, val);
 155        if (ret)
 156                return ret;
 157
 158        val = LP8727_INT_EN | LP8727_CHGDET_EN;
 159        return lp8727_write_byte(pchg, LP8727_CTRL2, val);
 160}
 161
 162static int lp8727_is_dedicated_charger(struct lp8727_chg *pchg)
 163{
 164        u8 val;
 165
 166        lp8727_read_byte(pchg, LP8727_STATUS1, &val);
 167        return val & LP8727_DCPORT;
 168}
 169
 170static int lp8727_is_usb_charger(struct lp8727_chg *pchg)
 171{
 172        u8 val;
 173
 174        lp8727_read_byte(pchg, LP8727_STATUS1, &val);
 175        return val & LP8727_CHPORT;
 176}
 177
 178static inline void lp8727_ctrl_switch(struct lp8727_chg *pchg, u8 sw)
 179{
 180        lp8727_write_byte(pchg, LP8727_SWCTRL, sw);
 181}
 182
 183static void lp8727_id_detection(struct lp8727_chg *pchg, u8 id, int vbusin)
 184{
 185        struct lp8727_platform_data *pdata = pchg->pdata;
 186        u8 devid = LP8727_ID_NONE;
 187        u8 swctrl = LP8727_SW_DM1_HiZ | LP8727_SW_DP2_HiZ;
 188
 189        switch (id) {
 190        case 0x5:
 191                devid = LP8727_ID_TA;
 192                pchg->chg_param = pdata ? pdata->ac : NULL;
 193                break;
 194        case 0xB:
 195                if (lp8727_is_dedicated_charger(pchg)) {
 196                        pchg->chg_param = pdata ? pdata->ac : NULL;
 197                        devid = LP8727_ID_DEDICATED_CHG;
 198                } else if (lp8727_is_usb_charger(pchg)) {
 199                        pchg->chg_param = pdata ? pdata->usb : NULL;
 200                        devid = LP8727_ID_USB_CHG;
 201                        swctrl = LP8727_SW_DM1_DM | LP8727_SW_DP2_DP;
 202                } else if (vbusin) {
 203                        devid = LP8727_ID_USB_DS;
 204                        swctrl = LP8727_SW_DM1_DM | LP8727_SW_DP2_DP;
 205                }
 206                break;
 207        default:
 208                devid = LP8727_ID_NONE;
 209                pchg->chg_param = NULL;
 210                break;
 211        }
 212
 213        pchg->devid = devid;
 214        lp8727_ctrl_switch(pchg, swctrl);
 215}
 216
 217static void lp8727_enable_chgdet(struct lp8727_chg *pchg)
 218{
 219        u8 val;
 220
 221        lp8727_read_byte(pchg, LP8727_CTRL2, &val);
 222        val |= LP8727_CHGDET_EN;
 223        lp8727_write_byte(pchg, LP8727_CTRL2, val);
 224}
 225
 226static void lp8727_delayed_func(struct work_struct *_work)
 227{
 228        struct lp8727_chg *pchg = container_of(_work, struct lp8727_chg,
 229                                                work.work);
 230        u8 intstat[LP8788_NUM_INTREGS];
 231        u8 idno;
 232        u8 vbus;
 233
 234        if (lp8727_read_bytes(pchg, LP8727_INT1, intstat, LP8788_NUM_INTREGS)) {
 235                dev_err(pchg->dev, "can not read INT registers\n");
 236                return;
 237        }
 238
 239        idno = intstat[0] & LP8727_IDNO;
 240        vbus = intstat[0] & LP8727_VBUS;
 241
 242        lp8727_id_detection(pchg, idno, vbus);
 243        lp8727_enable_chgdet(pchg);
 244
 245        power_supply_changed(&pchg->psy->ac);
 246        power_supply_changed(&pchg->psy->usb);
 247        power_supply_changed(&pchg->psy->batt);
 248}
 249
 250static irqreturn_t lp8727_isr_func(int irq, void *ptr)
 251{
 252        struct lp8727_chg *pchg = ptr;
 253
 254        schedule_delayed_work(&pchg->work, pchg->debounce_jiffies);
 255        return IRQ_HANDLED;
 256}
 257
 258static int lp8727_setup_irq(struct lp8727_chg *pchg)
 259{
 260        int ret;
 261        int irq = pchg->client->irq;
 262        unsigned delay_msec = pchg->pdata ? pchg->pdata->debounce_msec :
 263                                                DEFAULT_DEBOUNCE_MSEC;
 264
 265        INIT_DELAYED_WORK(&pchg->work, lp8727_delayed_func);
 266
 267        if (irq <= 0) {
 268                dev_warn(pchg->dev, "invalid irq number: %d\n", irq);
 269                return 0;
 270        }
 271
 272        ret = request_threaded_irq(irq, NULL, lp8727_isr_func,
 273                                IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
 274                                "lp8727_irq", pchg);
 275
 276        if (ret)
 277                return ret;
 278
 279        pchg->irq = irq;
 280        pchg->debounce_jiffies = msecs_to_jiffies(delay_msec);
 281
 282        return 0;
 283}
 284
 285static void lp8727_release_irq(struct lp8727_chg *pchg)
 286{
 287        cancel_delayed_work_sync(&pchg->work);
 288
 289        if (pchg->irq)
 290                free_irq(pchg->irq, pchg);
 291}
 292
 293static enum power_supply_property lp8727_charger_prop[] = {
 294        POWER_SUPPLY_PROP_ONLINE,
 295};
 296
 297static enum power_supply_property lp8727_battery_prop[] = {
 298        POWER_SUPPLY_PROP_STATUS,
 299        POWER_SUPPLY_PROP_HEALTH,
 300        POWER_SUPPLY_PROP_PRESENT,
 301        POWER_SUPPLY_PROP_VOLTAGE_NOW,
 302        POWER_SUPPLY_PROP_CAPACITY,
 303        POWER_SUPPLY_PROP_TEMP,
 304};
 305
 306static char *battery_supplied_to[] = {
 307        "main_batt",
 308};
 309
 310static int lp8727_charger_get_property(struct power_supply *psy,
 311                                       enum power_supply_property psp,
 312                                       union power_supply_propval *val)
 313{
 314        struct lp8727_chg *pchg = dev_get_drvdata(psy->dev->parent);
 315
 316        if (psp != POWER_SUPPLY_PROP_ONLINE)
 317                return -EINVAL;
 318
 319        val->intval = lp8727_is_charger_attached(psy->name, pchg->devid);
 320
 321        return 0;
 322}
 323
 324static bool lp8727_is_high_temperature(enum lp8727_die_temp temp)
 325{
 326        switch (temp) {
 327        case LP8788_TEMP_95C:
 328        case LP8788_TEMP_115C:
 329        case LP8788_TEMP_135C:
 330                return true;
 331        default:
 332                return false;
 333        }
 334}
 335
 336static int lp8727_battery_get_property(struct power_supply *psy,
 337                                       enum power_supply_property psp,
 338                                       union power_supply_propval *val)
 339{
 340        struct lp8727_chg *pchg = dev_get_drvdata(psy->dev->parent);
 341        struct lp8727_platform_data *pdata = pchg->pdata;
 342        enum lp8727_die_temp temp;
 343        u8 read;
 344
 345        switch (psp) {
 346        case POWER_SUPPLY_PROP_STATUS:
 347                if (!lp8727_is_charger_attached(psy->name, pchg->devid)) {
 348                        val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
 349                        return 0;
 350                }
 351
 352                lp8727_read_byte(pchg, LP8727_STATUS1, &read);
 353
 354                val->intval = (read & LP8727_CHGSTAT) == LP8727_STAT_EOC ?
 355                                POWER_SUPPLY_STATUS_FULL :
 356                                POWER_SUPPLY_STATUS_CHARGING;
 357                break;
 358        case POWER_SUPPLY_PROP_HEALTH:
 359                lp8727_read_byte(pchg, LP8727_STATUS2, &read);
 360                temp = (read & LP8727_TEMP_STAT) >> LP8727_TEMP_SHIFT;
 361
 362                val->intval = lp8727_is_high_temperature(temp) ?
 363                        POWER_SUPPLY_HEALTH_OVERHEAT :
 364                        POWER_SUPPLY_HEALTH_GOOD;
 365                break;
 366        case POWER_SUPPLY_PROP_PRESENT:
 367                if (!pdata)
 368                        return -EINVAL;
 369
 370                if (pdata->get_batt_present)
 371                        val->intval = pdata->get_batt_present();
 372                break;
 373        case POWER_SUPPLY_PROP_VOLTAGE_NOW:
 374                if (!pdata)
 375                        return -EINVAL;
 376
 377                if (pdata->get_batt_level)
 378                        val->intval = pdata->get_batt_level();
 379                break;
 380        case POWER_SUPPLY_PROP_CAPACITY:
 381                if (!pdata)
 382                        return -EINVAL;
 383
 384                if (pdata->get_batt_capacity)
 385                        val->intval = pdata->get_batt_capacity();
 386                break;
 387        case POWER_SUPPLY_PROP_TEMP:
 388                if (!pdata)
 389                        return -EINVAL;
 390
 391                if (pdata->get_batt_temp)
 392                        val->intval = pdata->get_batt_temp();
 393                break;
 394        default:
 395                break;
 396        }
 397
 398        return 0;
 399}
 400
 401static void lp8727_charger_changed(struct power_supply *psy)
 402{
 403        struct lp8727_chg *pchg = dev_get_drvdata(psy->dev->parent);
 404        u8 eoc_level;
 405        u8 ichg;
 406        u8 val;
 407
 408        /* skip if no charger exists */
 409        if (!lp8727_is_charger_attached(psy->name, pchg->devid))
 410                return;
 411
 412        /* update charging parameters */
 413        if (pchg->chg_param) {
 414                eoc_level = pchg->chg_param->eoc_level;
 415                ichg = pchg->chg_param->ichg;
 416                val = (ichg << LP8727_ICHG_SHIFT) | eoc_level;
 417                lp8727_write_byte(pchg, LP8727_CHGCTRL2, val);
 418        }
 419}
 420
 421static int lp8727_register_psy(struct lp8727_chg *pchg)
 422{
 423        struct lp8727_psy *psy;
 424
 425        psy = devm_kzalloc(pchg->dev, sizeof(*psy), GFP_KERNEL);
 426        if (!psy)
 427                return -ENOMEM;
 428
 429        pchg->psy = psy;
 430
 431        psy->ac.name = "ac";
 432        psy->ac.type = POWER_SUPPLY_TYPE_MAINS;
 433        psy->ac.properties = lp8727_charger_prop;
 434        psy->ac.num_properties = ARRAY_SIZE(lp8727_charger_prop);
 435        psy->ac.get_property = lp8727_charger_get_property;
 436        psy->ac.supplied_to = battery_supplied_to;
 437        psy->ac.num_supplicants = ARRAY_SIZE(battery_supplied_to);
 438
 439        if (power_supply_register(pchg->dev, &psy->ac))
 440                goto err_psy_ac;
 441
 442        psy->usb.name = "usb";
 443        psy->usb.type = POWER_SUPPLY_TYPE_USB;
 444        psy->usb.properties = lp8727_charger_prop;
 445        psy->usb.num_properties = ARRAY_SIZE(lp8727_charger_prop);
 446        psy->usb.get_property = lp8727_charger_get_property;
 447        psy->usb.supplied_to = battery_supplied_to;
 448        psy->usb.num_supplicants = ARRAY_SIZE(battery_supplied_to);
 449
 450        if (power_supply_register(pchg->dev, &psy->usb))
 451                goto err_psy_usb;
 452
 453        psy->batt.name = "main_batt";
 454        psy->batt.type = POWER_SUPPLY_TYPE_BATTERY;
 455        psy->batt.properties = lp8727_battery_prop;
 456        psy->batt.num_properties = ARRAY_SIZE(lp8727_battery_prop);
 457        psy->batt.get_property = lp8727_battery_get_property;
 458        psy->batt.external_power_changed = lp8727_charger_changed;
 459
 460        if (power_supply_register(pchg->dev, &psy->batt))
 461                goto err_psy_batt;
 462
 463        return 0;
 464
 465err_psy_batt:
 466        power_supply_unregister(&psy->usb);
 467err_psy_usb:
 468        power_supply_unregister(&psy->ac);
 469err_psy_ac:
 470        return -EPERM;
 471}
 472
 473static void lp8727_unregister_psy(struct lp8727_chg *pchg)
 474{
 475        struct lp8727_psy *psy = pchg->psy;
 476
 477        if (!psy)
 478                return;
 479
 480        power_supply_unregister(&psy->ac);
 481        power_supply_unregister(&psy->usb);
 482        power_supply_unregister(&psy->batt);
 483}
 484
 485#ifdef CONFIG_OF
 486static struct lp8727_chg_param
 487*lp8727_parse_charge_pdata(struct device *dev, struct device_node *np)
 488{
 489        struct lp8727_chg_param *param;
 490
 491        param = devm_kzalloc(dev, sizeof(*param), GFP_KERNEL);
 492        if (!param)
 493                goto out;
 494
 495        of_property_read_u8(np, "eoc-level", (u8 *)&param->eoc_level);
 496        of_property_read_u8(np, "charging-current", (u8 *)&param->ichg);
 497out:
 498        return param;
 499}
 500
 501static int lp8727_parse_dt(struct device *dev)
 502{
 503        struct device_node *np = dev->of_node;
 504        struct device_node *child;
 505        struct lp8727_platform_data *pdata;
 506        const char *type;
 507
 508        /* If charging parameter is not defined, just skip parsing the dt */
 509        if (of_get_child_count(np) == 0)
 510                goto out;
 511
 512        pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
 513        if (!pdata)
 514                return -ENOMEM;
 515
 516        of_property_read_u32(np, "debounce-ms", &pdata->debounce_msec);
 517
 518        for_each_child_of_node(np, child) {
 519                of_property_read_string(child, "charger-type", &type);
 520
 521                if (!strcmp(type, "ac"))
 522                        pdata->ac = lp8727_parse_charge_pdata(dev, child);
 523
 524                if (!strcmp(type, "usb"))
 525                        pdata->usb = lp8727_parse_charge_pdata(dev, child);
 526        }
 527
 528        dev->platform_data = pdata;
 529out:
 530        return 0;
 531}
 532#else
 533static int lp8727_parse_dt(struct device *dev)
 534{
 535        return 0;
 536}
 537#endif
 538
 539static int lp8727_probe(struct i2c_client *cl, const struct i2c_device_id *id)
 540{
 541        struct lp8727_chg *pchg;
 542        int ret;
 543
 544        if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
 545                return -EIO;
 546
 547        if (cl->dev.of_node) {
 548                ret = lp8727_parse_dt(&cl->dev);
 549                if (ret)
 550                        return ret;
 551        }
 552
 553        pchg = devm_kzalloc(&cl->dev, sizeof(*pchg), GFP_KERNEL);
 554        if (!pchg)
 555                return -ENOMEM;
 556
 557        pchg->client = cl;
 558        pchg->dev = &cl->dev;
 559        pchg->pdata = cl->dev.platform_data;
 560        i2c_set_clientdata(cl, pchg);
 561
 562        mutex_init(&pchg->xfer_lock);
 563
 564        ret = lp8727_init_device(pchg);
 565        if (ret) {
 566                dev_err(pchg->dev, "i2c communication err: %d", ret);
 567                return ret;
 568        }
 569
 570        ret = lp8727_register_psy(pchg);
 571        if (ret) {
 572                dev_err(pchg->dev, "power supplies register err: %d", ret);
 573                return ret;
 574        }
 575
 576        ret = lp8727_setup_irq(pchg);
 577        if (ret) {
 578                dev_err(pchg->dev, "irq handler err: %d", ret);
 579                lp8727_unregister_psy(pchg);
 580                return ret;
 581        }
 582
 583        return 0;
 584}
 585
 586static int lp8727_remove(struct i2c_client *cl)
 587{
 588        struct lp8727_chg *pchg = i2c_get_clientdata(cl);
 589
 590        lp8727_release_irq(pchg);
 591        lp8727_unregister_psy(pchg);
 592        return 0;
 593}
 594
 595static const struct of_device_id lp8727_dt_ids[] = {
 596        { .compatible = "ti,lp8727", },
 597        { }
 598};
 599MODULE_DEVICE_TABLE(of, lp8727_dt_ids);
 600
 601static const struct i2c_device_id lp8727_ids[] = {
 602        {"lp8727", 0},
 603        { }
 604};
 605MODULE_DEVICE_TABLE(i2c, lp8727_ids);
 606
 607static struct i2c_driver lp8727_driver = {
 608        .driver = {
 609                   .name = "lp8727",
 610                   .of_match_table = of_match_ptr(lp8727_dt_ids),
 611                   },
 612        .probe = lp8727_probe,
 613        .remove = lp8727_remove,
 614        .id_table = lp8727_ids,
 615};
 616module_i2c_driver(lp8727_driver);
 617
 618MODULE_DESCRIPTION("TI/National Semiconductor LP8727 charger driver");
 619MODULE_AUTHOR("Milo Kim <milo.kim@ti.com>, Daniel Jeong <daniel.jeong@ti.com>");
 620MODULE_LICENSE("GPL");
 621
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.