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->desc->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->desc->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->desc->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 const struct power_supply_desc lp8727_ac_desc = {
 422        .name                   = "ac",
 423        .type                   = POWER_SUPPLY_TYPE_MAINS,
 424        .properties             = lp8727_charger_prop,
 425        .num_properties         = ARRAY_SIZE(lp8727_charger_prop),
 426        .get_property           = lp8727_charger_get_property,
 427};
 428
 429static const struct power_supply_desc lp8727_usb_desc = {
 430        .name                   = "usb",
 431        .type                   = POWER_SUPPLY_TYPE_USB,
 432        .properties             = lp8727_charger_prop,
 433        .num_properties         = ARRAY_SIZE(lp8727_charger_prop),
 434        .get_property           = lp8727_charger_get_property,
 435};
 436
 437static const struct power_supply_desc lp8727_batt_desc = {
 438        .name                   = "main_batt",
 439        .type                   = POWER_SUPPLY_TYPE_BATTERY,
 440        .properties             = lp8727_battery_prop,
 441        .num_properties         = ARRAY_SIZE(lp8727_battery_prop),
 442        .get_property           = lp8727_battery_get_property,
 443        .external_power_changed = lp8727_charger_changed,
 444};
 445
 446static int lp8727_register_psy(struct lp8727_chg *pchg)
 447{
 448        struct power_supply_config psy_cfg = {}; /* Only for ac and usb */
 449        struct lp8727_psy *psy;
 450
 451        psy = devm_kzalloc(pchg->dev, sizeof(*psy), GFP_KERNEL);
 452        if (!psy)
 453                return -ENOMEM;
 454
 455        pchg->psy = psy;
 456
 457        psy_cfg.supplied_to = battery_supplied_to;
 458        psy_cfg.num_supplicants = ARRAY_SIZE(battery_supplied_to);
 459
 460        psy->ac = power_supply_register(pchg->dev, &lp8727_ac_desc, &psy_cfg);
 461        if (IS_ERR(psy->ac))
 462                goto err_psy_ac;
 463
 464        psy->usb = power_supply_register(pchg->dev, &lp8727_usb_desc,
 465                                         &psy_cfg);
 466        if (IS_ERR(psy->usb))
 467                goto err_psy_usb;
 468
 469        psy->batt = power_supply_register(pchg->dev, &lp8727_batt_desc, NULL);
 470        if (IS_ERR(psy->batt))
 471                goto err_psy_batt;
 472
 473        return 0;
 474
 475err_psy_batt:
 476        power_supply_unregister(psy->usb);
 477err_psy_usb:
 478        power_supply_unregister(psy->ac);
 479err_psy_ac:
 480        return -EPERM;
 481}
 482
 483static void lp8727_unregister_psy(struct lp8727_chg *pchg)
 484{
 485        struct lp8727_psy *psy = pchg->psy;
 486
 487        if (!psy)
 488                return;
 489
 490        power_supply_unregister(psy->ac);
 491        power_supply_unregister(psy->usb);
 492        power_supply_unregister(psy->batt);
 493}
 494
 495#ifdef CONFIG_OF
 496static struct lp8727_chg_param
 497*lp8727_parse_charge_pdata(struct device *dev, struct device_node *np)
 498{
 499        struct lp8727_chg_param *param;
 500
 501        param = devm_kzalloc(dev, sizeof(*param), GFP_KERNEL);
 502        if (!param)
 503                goto out;
 504
 505        of_property_read_u8(np, "eoc-level", (u8 *)&param->eoc_level);
 506        of_property_read_u8(np, "charging-current", (u8 *)&param->ichg);
 507out:
 508        return param;
 509}
 510
 511static int lp8727_parse_dt(struct device *dev)
 512{
 513        struct device_node *np = dev->of_node;
 514        struct device_node *child;
 515        struct lp8727_platform_data *pdata;
 516        const char *type;
 517
 518        /* If charging parameter is not defined, just skip parsing the dt */
 519        if (of_get_child_count(np) == 0)
 520                goto out;
 521
 522        pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
 523        if (!pdata)
 524                return -ENOMEM;
 525
 526        of_property_read_u32(np, "debounce-ms", &pdata->debounce_msec);
 527
 528        for_each_child_of_node(np, child) {
 529                of_property_read_string(child, "charger-type", &type);
 530
 531                if (!strcmp(type, "ac"))
 532                        pdata->ac = lp8727_parse_charge_pdata(dev, child);
 533
 534                if (!strcmp(type, "usb"))
 535                        pdata->usb = lp8727_parse_charge_pdata(dev, child);
 536        }
 537
 538        dev->platform_data = pdata;
 539out:
 540        return 0;
 541}
 542#else
 543static int lp8727_parse_dt(struct device *dev)
 544{
 545        return 0;
 546}
 547#endif
 548
 549static int lp8727_probe(struct i2c_client *cl, const struct i2c_device_id *id)
 550{
 551        struct lp8727_chg *pchg;
 552        int ret;
 553
 554        if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
 555                return -EIO;
 556
 557        if (cl->dev.of_node) {
 558                ret = lp8727_parse_dt(&cl->dev);
 559                if (ret)
 560                        return ret;
 561        }
 562
 563        pchg = devm_kzalloc(&cl->dev, sizeof(*pchg), GFP_KERNEL);
 564        if (!pchg)
 565                return -ENOMEM;
 566
 567        pchg->client = cl;
 568        pchg->dev = &cl->dev;
 569        pchg->pdata = cl->dev.platform_data;
 570        i2c_set_clientdata(cl, pchg);
 571
 572        mutex_init(&pchg->xfer_lock);
 573
 574        ret = lp8727_init_device(pchg);
 575        if (ret) {
 576                dev_err(pchg->dev, "i2c communication err: %d", ret);
 577                return ret;
 578        }
 579
 580        ret = lp8727_register_psy(pchg);
 581        if (ret) {
 582                dev_err(pchg->dev, "power supplies register err: %d", ret);
 583                return ret;
 584        }
 585
 586        ret = lp8727_setup_irq(pchg);
 587        if (ret) {
 588                dev_err(pchg->dev, "irq handler err: %d", ret);
 589                lp8727_unregister_psy(pchg);
 590                return ret;
 591        }
 592
 593        return 0;
 594}
 595
 596static int lp8727_remove(struct i2c_client *cl)
 597{
 598        struct lp8727_chg *pchg = i2c_get_clientdata(cl);
 599
 600        lp8727_release_irq(pchg);
 601        lp8727_unregister_psy(pchg);
 602        return 0;
 603}
 604
 605static const struct of_device_id lp8727_dt_ids[] = {
 606        { .compatible = "ti,lp8727", },
 607        { }
 608};
 609MODULE_DEVICE_TABLE(of, lp8727_dt_ids);
 610
 611static const struct i2c_device_id lp8727_ids[] = {
 612        {"lp8727", 0},
 613        { }
 614};
 615MODULE_DEVICE_TABLE(i2c, lp8727_ids);
 616
 617static struct i2c_driver lp8727_driver = {
 618        .driver = {
 619                   .name = "lp8727",
 620                   .of_match_table = of_match_ptr(lp8727_dt_ids),
 621                   },
 622        .probe = lp8727_probe,
 623        .remove = lp8727_remove,
 624        .id_table = lp8727_ids,
 625};
 626module_i2c_driver(lp8727_driver);
 627
 628MODULE_DESCRIPTION("TI/National Semiconductor LP8727 charger driver");
 629MODULE_AUTHOR("Milo Kim <milo.kim@ti.com>, Daniel Jeong <daniel.jeong@ti.com>");
 630MODULE_LICENSE("GPL");
 631