linux/drivers/power/supply/lp8788-charger.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * TI LP8788 MFD - battery charger driver
   4 *
   5 * Copyright 2012 Texas Instruments
   6 *
   7 * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
   8 */
   9
  10#include <linux/err.h>
  11#include <linux/iio/consumer.h>
  12#include <linux/interrupt.h>
  13#include <linux/irqdomain.h>
  14#include <linux/mfd/lp8788.h>
  15#include <linux/module.h>
  16#include <linux/platform_device.h>
  17#include <linux/power_supply.h>
  18#include <linux/slab.h>
  19#include <linux/workqueue.h>
  20
  21/* register address */
  22#define LP8788_CHG_STATUS               0x07
  23#define LP8788_CHG_IDCIN                0x13
  24#define LP8788_CHG_IBATT                0x14
  25#define LP8788_CHG_VTERM                0x15
  26#define LP8788_CHG_EOC                  0x16
  27
  28/* mask/shift bits */
  29#define LP8788_CHG_INPUT_STATE_M        0x03    /* Addr 07h */
  30#define LP8788_CHG_STATE_M              0x3C
  31#define LP8788_CHG_STATE_S              2
  32#define LP8788_NO_BATT_M                BIT(6)
  33#define LP8788_BAD_BATT_M               BIT(7)
  34#define LP8788_CHG_IBATT_M              0x1F    /* Addr 14h */
  35#define LP8788_CHG_VTERM_M              0x0F    /* Addr 15h */
  36#define LP8788_CHG_EOC_LEVEL_M          0x30    /* Addr 16h */
  37#define LP8788_CHG_EOC_LEVEL_S          4
  38#define LP8788_CHG_EOC_TIME_M           0x0E
  39#define LP8788_CHG_EOC_TIME_S           1
  40#define LP8788_CHG_EOC_MODE_M           BIT(0)
  41
  42#define LP8788_CHARGER_NAME             "charger"
  43#define LP8788_BATTERY_NAME             "main_batt"
  44
  45#define LP8788_CHG_START                0x11
  46#define LP8788_CHG_END                  0x1C
  47
  48#define LP8788_ISEL_MAX                 23
  49#define LP8788_ISEL_STEP                50
  50#define LP8788_VTERM_MIN                4100
  51#define LP8788_VTERM_STEP               25
  52#define LP8788_MAX_BATT_CAPACITY        100
  53#define LP8788_MAX_CHG_IRQS             11
  54
  55enum lp8788_charging_state {
  56        LP8788_OFF,
  57        LP8788_WARM_UP,
  58        LP8788_LOW_INPUT = 0x3,
  59        LP8788_PRECHARGE,
  60        LP8788_CC,
  61        LP8788_CV,
  62        LP8788_MAINTENANCE,
  63        LP8788_BATTERY_FAULT,
  64        LP8788_SYSTEM_SUPPORT = 0xC,
  65        LP8788_HIGH_CURRENT = 0xF,
  66        LP8788_MAX_CHG_STATE,
  67};
  68
  69enum lp8788_charger_adc_sel {
  70        LP8788_VBATT,
  71        LP8788_BATT_TEMP,
  72        LP8788_NUM_CHG_ADC,
  73};
  74
  75enum lp8788_charger_input_state {
  76        LP8788_SYSTEM_SUPPLY = 1,
  77        LP8788_FULL_FUNCTION,
  78};
  79
  80/*
  81 * struct lp8788_chg_irq
  82 * @which        : lp8788 interrupt id
  83 * @virq         : Linux IRQ number from irq_domain
  84 */
  85struct lp8788_chg_irq {
  86        enum lp8788_int_id which;
  87        int virq;
  88};
  89
  90/*
  91 * struct lp8788_charger
  92 * @lp           : used for accessing the registers of mfd lp8788 device
  93 * @charger      : power supply driver for the battery charger
  94 * @battery      : power supply driver for the battery
  95 * @charger_work : work queue for charger input interrupts
  96 * @chan         : iio channels for getting adc values
  97 *                 eg) battery voltage, capacity and temperature
  98 * @irqs         : charger dedicated interrupts
  99 * @num_irqs     : total numbers of charger interrupts
 100 * @pdata        : charger platform specific data
 101 */
 102struct lp8788_charger {
 103        struct lp8788 *lp;
 104        struct power_supply *charger;
 105        struct power_supply *battery;
 106        struct work_struct charger_work;
 107        struct iio_channel *chan[LP8788_NUM_CHG_ADC];
 108        struct lp8788_chg_irq irqs[LP8788_MAX_CHG_IRQS];
 109        int num_irqs;
 110        struct lp8788_charger_platform_data *pdata;
 111};
 112
 113static char *battery_supplied_to[] = {
 114        LP8788_BATTERY_NAME,
 115};
 116
 117static enum power_supply_property lp8788_charger_prop[] = {
 118        POWER_SUPPLY_PROP_ONLINE,
 119        POWER_SUPPLY_PROP_CURRENT_MAX,
 120};
 121
 122static enum power_supply_property lp8788_battery_prop[] = {
 123        POWER_SUPPLY_PROP_STATUS,
 124        POWER_SUPPLY_PROP_HEALTH,
 125        POWER_SUPPLY_PROP_PRESENT,
 126        POWER_SUPPLY_PROP_VOLTAGE_NOW,
 127        POWER_SUPPLY_PROP_CAPACITY,
 128        POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
 129        POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
 130        POWER_SUPPLY_PROP_TEMP,
 131};
 132
 133static bool lp8788_is_charger_detected(struct lp8788_charger *pchg)
 134{
 135        u8 data;
 136
 137        lp8788_read_byte(pchg->lp, LP8788_CHG_STATUS, &data);
 138        data &= LP8788_CHG_INPUT_STATE_M;
 139
 140        return data == LP8788_SYSTEM_SUPPLY || data == LP8788_FULL_FUNCTION;
 141}
 142
 143static int lp8788_charger_get_property(struct power_supply *psy,
 144                                        enum power_supply_property psp,
 145                                        union power_supply_propval *val)
 146{
 147        struct lp8788_charger *pchg = dev_get_drvdata(psy->dev.parent);
 148        u8 read;
 149
 150        switch (psp) {
 151        case POWER_SUPPLY_PROP_ONLINE:
 152                val->intval = lp8788_is_charger_detected(pchg);
 153                break;
 154        case POWER_SUPPLY_PROP_CURRENT_MAX:
 155                lp8788_read_byte(pchg->lp, LP8788_CHG_IDCIN, &read);
 156                val->intval = LP8788_ISEL_STEP *
 157                                (min_t(int, read, LP8788_ISEL_MAX) + 1);
 158                break;
 159        default:
 160                return -EINVAL;
 161        }
 162
 163        return 0;
 164}
 165
 166static int lp8788_get_battery_status(struct lp8788_charger *pchg,
 167                                union power_supply_propval *val)
 168{
 169        enum lp8788_charging_state state;
 170        u8 data;
 171        int ret;
 172
 173        ret = lp8788_read_byte(pchg->lp, LP8788_CHG_STATUS, &data);
 174        if (ret)
 175                return ret;
 176
 177        state = (data & LP8788_CHG_STATE_M) >> LP8788_CHG_STATE_S;
 178        switch (state) {
 179        case LP8788_OFF:
 180                val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
 181                break;
 182        case LP8788_PRECHARGE:
 183        case LP8788_CC:
 184        case LP8788_CV:
 185        case LP8788_HIGH_CURRENT:
 186                val->intval = POWER_SUPPLY_STATUS_CHARGING;
 187                break;
 188        case LP8788_MAINTENANCE:
 189                val->intval = POWER_SUPPLY_STATUS_FULL;
 190                break;
 191        default:
 192                val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
 193                break;
 194        }
 195
 196        return 0;
 197}
 198
 199static int lp8788_get_battery_health(struct lp8788_charger *pchg,
 200                                union power_supply_propval *val)
 201{
 202        u8 data;
 203        int ret;
 204
 205        ret = lp8788_read_byte(pchg->lp, LP8788_CHG_STATUS, &data);
 206        if (ret)
 207                return ret;
 208
 209        if (data & LP8788_NO_BATT_M)
 210                val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
 211        else if (data & LP8788_BAD_BATT_M)
 212                val->intval = POWER_SUPPLY_HEALTH_DEAD;
 213        else
 214                val->intval = POWER_SUPPLY_HEALTH_GOOD;
 215
 216        return 0;
 217}
 218
 219static int lp8788_get_battery_present(struct lp8788_charger *pchg,
 220                                union power_supply_propval *val)
 221{
 222        u8 data;
 223        int ret;
 224
 225        ret = lp8788_read_byte(pchg->lp, LP8788_CHG_STATUS, &data);
 226        if (ret)
 227                return ret;
 228
 229        val->intval = !(data & LP8788_NO_BATT_M);
 230        return 0;
 231}
 232
 233static int lp8788_get_vbatt_adc(struct lp8788_charger *pchg, int *result)
 234{
 235        struct iio_channel *channel = pchg->chan[LP8788_VBATT];
 236
 237        if (!channel)
 238                return -EINVAL;
 239
 240        return iio_read_channel_processed(channel, result);
 241}
 242
 243static int lp8788_get_battery_voltage(struct lp8788_charger *pchg,
 244                                union power_supply_propval *val)
 245{
 246        return lp8788_get_vbatt_adc(pchg, &val->intval);
 247}
 248
 249static int lp8788_get_battery_capacity(struct lp8788_charger *pchg,
 250                                union power_supply_propval *val)
 251{
 252        struct lp8788 *lp = pchg->lp;
 253        struct lp8788_charger_platform_data *pdata = pchg->pdata;
 254        unsigned int max_vbatt;
 255        int vbatt;
 256        enum lp8788_charging_state state;
 257        u8 data;
 258        int ret;
 259
 260        if (!pdata)
 261                return -EINVAL;
 262
 263        max_vbatt = pdata->max_vbatt_mv;
 264        if (max_vbatt == 0)
 265                return -EINVAL;
 266
 267        ret = lp8788_read_byte(lp, LP8788_CHG_STATUS, &data);
 268        if (ret)
 269                return ret;
 270
 271        state = (data & LP8788_CHG_STATE_M) >> LP8788_CHG_STATE_S;
 272
 273        if (state == LP8788_MAINTENANCE) {
 274                val->intval = LP8788_MAX_BATT_CAPACITY;
 275        } else {
 276                ret = lp8788_get_vbatt_adc(pchg, &vbatt);
 277                if (ret)
 278                        return ret;
 279
 280                val->intval = (vbatt * LP8788_MAX_BATT_CAPACITY) / max_vbatt;
 281                val->intval = min(val->intval, LP8788_MAX_BATT_CAPACITY);
 282        }
 283
 284        return 0;
 285}
 286
 287static int lp8788_get_battery_temperature(struct lp8788_charger *pchg,
 288                                union power_supply_propval *val)
 289{
 290        struct iio_channel *channel = pchg->chan[LP8788_BATT_TEMP];
 291        int result;
 292        int ret;
 293
 294        if (!channel)
 295                return -EINVAL;
 296
 297        ret = iio_read_channel_processed(channel, &result);
 298        if (ret < 0)
 299                return -EINVAL;
 300
 301        /* unit: 0.1 'C */
 302        val->intval = result * 10;
 303
 304        return 0;
 305}
 306
 307static int lp8788_get_battery_charging_current(struct lp8788_charger *pchg,
 308                                union power_supply_propval *val)
 309{
 310        u8 read;
 311
 312        lp8788_read_byte(pchg->lp, LP8788_CHG_IBATT, &read);
 313        read &= LP8788_CHG_IBATT_M;
 314        val->intval = LP8788_ISEL_STEP *
 315                        (min_t(int, read, LP8788_ISEL_MAX) + 1);
 316
 317        return 0;
 318}
 319
 320static int lp8788_get_charging_termination_voltage(struct lp8788_charger *pchg,
 321                                union power_supply_propval *val)
 322{
 323        u8 read;
 324
 325        lp8788_read_byte(pchg->lp, LP8788_CHG_VTERM, &read);
 326        read &= LP8788_CHG_VTERM_M;
 327        val->intval = LP8788_VTERM_MIN + LP8788_VTERM_STEP * read;
 328
 329        return 0;
 330}
 331
 332static int lp8788_battery_get_property(struct power_supply *psy,
 333                                        enum power_supply_property psp,
 334                                        union power_supply_propval *val)
 335{
 336        struct lp8788_charger *pchg = dev_get_drvdata(psy->dev.parent);
 337
 338        switch (psp) {
 339        case POWER_SUPPLY_PROP_STATUS:
 340                return lp8788_get_battery_status(pchg, val);
 341        case POWER_SUPPLY_PROP_HEALTH:
 342                return lp8788_get_battery_health(pchg, val);
 343        case POWER_SUPPLY_PROP_PRESENT:
 344                return lp8788_get_battery_present(pchg, val);
 345        case POWER_SUPPLY_PROP_VOLTAGE_NOW:
 346                return lp8788_get_battery_voltage(pchg, val);
 347        case POWER_SUPPLY_PROP_CAPACITY:
 348                return lp8788_get_battery_capacity(pchg, val);
 349        case POWER_SUPPLY_PROP_TEMP:
 350                return lp8788_get_battery_temperature(pchg, val);
 351        case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
 352                return lp8788_get_battery_charging_current(pchg, val);
 353        case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
 354                return lp8788_get_charging_termination_voltage(pchg, val);
 355        default:
 356                return -EINVAL;
 357        }
 358}
 359
 360static inline bool lp8788_is_valid_charger_register(u8 addr)
 361{
 362        return addr >= LP8788_CHG_START && addr <= LP8788_CHG_END;
 363}
 364
 365static int lp8788_update_charger_params(struct platform_device *pdev,
 366                                        struct lp8788_charger *pchg)
 367{
 368        struct lp8788 *lp = pchg->lp;
 369        struct lp8788_charger_platform_data *pdata = pchg->pdata;
 370        struct lp8788_chg_param *param;
 371        int i;
 372        int ret;
 373
 374        if (!pdata || !pdata->chg_params) {
 375                dev_info(&pdev->dev, "skip updating charger parameters\n");
 376                return 0;
 377        }
 378
 379        /* settting charging parameters */
 380        for (i = 0; i < pdata->num_chg_params; i++) {
 381                param = pdata->chg_params + i;
 382
 383                if (lp8788_is_valid_charger_register(param->addr)) {
 384                        ret = lp8788_write_byte(lp, param->addr, param->val);
 385                        if (ret)
 386                                return ret;
 387                }
 388        }
 389
 390        return 0;
 391}
 392
 393static const struct power_supply_desc lp8788_psy_charger_desc = {
 394        .name           = LP8788_CHARGER_NAME,
 395        .type           = POWER_SUPPLY_TYPE_MAINS,
 396        .properties     = lp8788_charger_prop,
 397        .num_properties = ARRAY_SIZE(lp8788_charger_prop),
 398        .get_property   = lp8788_charger_get_property,
 399};
 400
 401static const struct power_supply_desc lp8788_psy_battery_desc = {
 402        .name           = LP8788_BATTERY_NAME,
 403        .type           = POWER_SUPPLY_TYPE_BATTERY,
 404        .properties     = lp8788_battery_prop,
 405        .num_properties = ARRAY_SIZE(lp8788_battery_prop),
 406        .get_property   = lp8788_battery_get_property,
 407};
 408
 409static void lp8788_psy_unregister(struct lp8788_charger *pchg)
 410{
 411        power_supply_unregister(pchg->battery);
 412        power_supply_unregister(pchg->charger);
 413}
 414
 415static void lp8788_charger_event(struct work_struct *work)
 416{
 417        struct lp8788_charger *pchg =
 418                container_of(work, struct lp8788_charger, charger_work);
 419        struct lp8788_charger_platform_data *pdata = pchg->pdata;
 420        enum lp8788_charger_event event = lp8788_is_charger_detected(pchg);
 421
 422        pdata->charger_event(pchg->lp, event);
 423}
 424
 425static bool lp8788_find_irq_id(struct lp8788_charger *pchg, int virq, int *id)
 426{
 427        bool found = false;
 428        int i;
 429
 430        for (i = 0; i < pchg->num_irqs; i++) {
 431                if (pchg->irqs[i].virq == virq) {
 432                        *id = pchg->irqs[i].which;
 433                        found = true;
 434                        break;
 435                }
 436        }
 437
 438        return found;
 439}
 440
 441static irqreturn_t lp8788_charger_irq_thread(int virq, void *ptr)
 442{
 443        struct lp8788_charger *pchg = ptr;
 444        struct lp8788_charger_platform_data *pdata = pchg->pdata;
 445        int id = -1;
 446
 447        if (!lp8788_find_irq_id(pchg, virq, &id))
 448                return IRQ_NONE;
 449
 450        switch (id) {
 451        case LP8788_INT_CHG_INPUT_STATE:
 452        case LP8788_INT_CHG_STATE:
 453        case LP8788_INT_EOC:
 454        case LP8788_INT_BATT_LOW:
 455        case LP8788_INT_NO_BATT:
 456                power_supply_changed(pchg->charger);
 457                power_supply_changed(pchg->battery);
 458                break;
 459        default:
 460                break;
 461        }
 462
 463        /* report charger dectection event if used */
 464        if (!pdata)
 465                goto irq_handled;
 466
 467        if (pdata->charger_event && id == LP8788_INT_CHG_INPUT_STATE)
 468                schedule_work(&pchg->charger_work);
 469
 470irq_handled:
 471        return IRQ_HANDLED;
 472}
 473
 474static int lp8788_set_irqs(struct platform_device *pdev,
 475                        struct lp8788_charger *pchg, const char *name)
 476{
 477        struct resource *r;
 478        struct irq_domain *irqdm = pchg->lp->irqdm;
 479        int irq_start;
 480        int irq_end;
 481        int virq;
 482        int nr_irq;
 483        int i;
 484        int ret;
 485
 486        /* no error even if no irq resource */
 487        r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, name);
 488        if (!r)
 489                return 0;
 490
 491        irq_start = r->start;
 492        irq_end = r->end;
 493
 494        for (i = irq_start; i <= irq_end; i++) {
 495                nr_irq = pchg->num_irqs;
 496
 497                virq = irq_create_mapping(irqdm, i);
 498                pchg->irqs[nr_irq].virq = virq;
 499                pchg->irqs[nr_irq].which = i;
 500                pchg->num_irqs++;
 501
 502                ret = request_threaded_irq(virq, NULL,
 503                                        lp8788_charger_irq_thread,
 504                                        0, name, pchg);
 505                if (ret)
 506                        break;
 507        }
 508
 509        if (i <= irq_end)
 510                goto err_free_irq;
 511
 512        return 0;
 513
 514err_free_irq:
 515        for (i = 0; i < pchg->num_irqs; i++)
 516                free_irq(pchg->irqs[i].virq, pchg);
 517        return ret;
 518}
 519
 520static int lp8788_irq_register(struct platform_device *pdev,
 521                                struct lp8788_charger *pchg)
 522{
 523        const char *name[] = {
 524                LP8788_CHG_IRQ, LP8788_PRSW_IRQ, LP8788_BATT_IRQ
 525        };
 526        int i;
 527        int ret;
 528
 529        INIT_WORK(&pchg->charger_work, lp8788_charger_event);
 530        pchg->num_irqs = 0;
 531
 532        for (i = 0; i < ARRAY_SIZE(name); i++) {
 533                ret = lp8788_set_irqs(pdev, pchg, name[i]);
 534                if (ret) {
 535                        dev_warn(&pdev->dev, "irq setup failed: %s\n", name[i]);
 536                        return ret;
 537                }
 538        }
 539
 540        if (pchg->num_irqs > LP8788_MAX_CHG_IRQS) {
 541                dev_err(&pdev->dev, "invalid total number of irqs: %d\n",
 542                        pchg->num_irqs);
 543                return -EINVAL;
 544        }
 545
 546
 547        return 0;
 548}
 549
 550static void lp8788_irq_unregister(struct platform_device *pdev,
 551                                  struct lp8788_charger *pchg)
 552{
 553        int i;
 554        int irq;
 555
 556        for (i = 0; i < pchg->num_irqs; i++) {
 557                irq = pchg->irqs[i].virq;
 558                if (!irq)
 559                        continue;
 560
 561                free_irq(irq, pchg);
 562        }
 563}
 564
 565static void lp8788_setup_adc_channel(struct device *dev,
 566                                struct lp8788_charger *pchg)
 567{
 568        struct lp8788_charger_platform_data *pdata = pchg->pdata;
 569        struct iio_channel *chan;
 570
 571        if (!pdata)
 572                return;
 573
 574        /* ADC channel for battery voltage */
 575        chan = iio_channel_get(dev, pdata->adc_vbatt);
 576        pchg->chan[LP8788_VBATT] = IS_ERR(chan) ? NULL : chan;
 577
 578        /* ADC channel for battery temperature */
 579        chan = iio_channel_get(dev, pdata->adc_batt_temp);
 580        pchg->chan[LP8788_BATT_TEMP] = IS_ERR(chan) ? NULL : chan;
 581}
 582
 583static void lp8788_release_adc_channel(struct lp8788_charger *pchg)
 584{
 585        int i;
 586
 587        for (i = 0; i < LP8788_NUM_CHG_ADC; i++) {
 588                if (!pchg->chan[i])
 589                        continue;
 590
 591                iio_channel_release(pchg->chan[i]);
 592                pchg->chan[i] = NULL;
 593        }
 594}
 595
 596static ssize_t lp8788_show_charger_status(struct device *dev,
 597                                struct device_attribute *attr, char *buf)
 598{
 599        struct lp8788_charger *pchg = dev_get_drvdata(dev);
 600        enum lp8788_charging_state state;
 601        static const char * const desc[LP8788_MAX_CHG_STATE] = {
 602                [LP8788_OFF] = "CHARGER OFF",
 603                [LP8788_WARM_UP] = "WARM UP",
 604                [LP8788_LOW_INPUT] = "LOW INPUT STATE",
 605                [LP8788_PRECHARGE] = "CHARGING - PRECHARGE",
 606                [LP8788_CC] = "CHARGING - CC",
 607                [LP8788_CV] = "CHARGING - CV",
 608                [LP8788_MAINTENANCE] = "NO CHARGING - MAINTENANCE",
 609                [LP8788_BATTERY_FAULT] = "BATTERY FAULT",
 610                [LP8788_SYSTEM_SUPPORT] = "SYSTEM SUPPORT",
 611                [LP8788_HIGH_CURRENT] = "HIGH CURRENT",
 612        };
 613        u8 data;
 614
 615        lp8788_read_byte(pchg->lp, LP8788_CHG_STATUS, &data);
 616        state = (data & LP8788_CHG_STATE_M) >> LP8788_CHG_STATE_S;
 617
 618        return scnprintf(buf, PAGE_SIZE, "%s\n", desc[state]);
 619}
 620
 621static ssize_t lp8788_show_eoc_time(struct device *dev,
 622                                struct device_attribute *attr, char *buf)
 623{
 624        struct lp8788_charger *pchg = dev_get_drvdata(dev);
 625        static const char * const stime[] = {
 626                "400ms", "5min", "10min", "15min",
 627                "20min", "25min", "30min", "No timeout"
 628        };
 629        u8 val;
 630
 631        lp8788_read_byte(pchg->lp, LP8788_CHG_EOC, &val);
 632        val = (val & LP8788_CHG_EOC_TIME_M) >> LP8788_CHG_EOC_TIME_S;
 633
 634        return scnprintf(buf, PAGE_SIZE, "End Of Charge Time: %s\n",
 635                        stime[val]);
 636}
 637
 638static ssize_t lp8788_show_eoc_level(struct device *dev,
 639                                struct device_attribute *attr, char *buf)
 640{
 641        struct lp8788_charger *pchg = dev_get_drvdata(dev);
 642        static const char * const abs_level[] = {
 643                        "25mA", "49mA", "75mA", "98mA"
 644        };
 645        static const char * const relative_level[] = {
 646                        "5%", "10%", "15%", "20%"
 647        };
 648        const char *level;
 649        u8 val;
 650        u8 mode;
 651
 652        lp8788_read_byte(pchg->lp, LP8788_CHG_EOC, &val);
 653
 654        mode = val & LP8788_CHG_EOC_MODE_M;
 655        val = (val & LP8788_CHG_EOC_LEVEL_M) >> LP8788_CHG_EOC_LEVEL_S;
 656        level = mode ? abs_level[val] : relative_level[val];
 657
 658        return scnprintf(buf, PAGE_SIZE, "End Of Charge Level: %s\n", level);
 659}
 660
 661static DEVICE_ATTR(charger_status, S_IRUSR, lp8788_show_charger_status, NULL);
 662static DEVICE_ATTR(eoc_time, S_IRUSR, lp8788_show_eoc_time, NULL);
 663static DEVICE_ATTR(eoc_level, S_IRUSR, lp8788_show_eoc_level, NULL);
 664
 665static struct attribute *lp8788_charger_sysfs_attrs[] = {
 666        &dev_attr_charger_status.attr,
 667        &dev_attr_eoc_time.attr,
 668        &dev_attr_eoc_level.attr,
 669        NULL,
 670};
 671
 672ATTRIBUTE_GROUPS(lp8788_charger_sysfs);
 673
 674static int lp8788_psy_register(struct platform_device *pdev,
 675                                struct lp8788_charger *pchg)
 676{
 677        struct power_supply_config charger_cfg = {};
 678
 679        charger_cfg.attr_grp = lp8788_charger_sysfs_groups;
 680        charger_cfg.supplied_to = battery_supplied_to;
 681        charger_cfg.num_supplicants = ARRAY_SIZE(battery_supplied_to);
 682
 683        pchg->charger = power_supply_register(&pdev->dev,
 684                                              &lp8788_psy_charger_desc,
 685                                              &charger_cfg);
 686        if (IS_ERR(pchg->charger))
 687                return -EPERM;
 688
 689        pchg->battery = power_supply_register(&pdev->dev,
 690                                              &lp8788_psy_battery_desc, NULL);
 691        if (IS_ERR(pchg->battery)) {
 692                power_supply_unregister(pchg->charger);
 693                return -EPERM;
 694        }
 695
 696        return 0;
 697}
 698
 699static int lp8788_charger_probe(struct platform_device *pdev)
 700{
 701        struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
 702        struct lp8788_charger *pchg;
 703        struct device *dev = &pdev->dev;
 704        int ret;
 705
 706        pchg = devm_kzalloc(dev, sizeof(struct lp8788_charger), GFP_KERNEL);
 707        if (!pchg)
 708                return -ENOMEM;
 709
 710        pchg->lp = lp;
 711        pchg->pdata = lp->pdata ? lp->pdata->chg_pdata : NULL;
 712        platform_set_drvdata(pdev, pchg);
 713
 714        ret = lp8788_update_charger_params(pdev, pchg);
 715        if (ret)
 716                return ret;
 717
 718        lp8788_setup_adc_channel(&pdev->dev, pchg);
 719
 720        ret = lp8788_psy_register(pdev, pchg);
 721        if (ret)
 722                return ret;
 723
 724        ret = lp8788_irq_register(pdev, pchg);
 725        if (ret)
 726                dev_warn(dev, "failed to register charger irq: %d\n", ret);
 727
 728        return 0;
 729}
 730
 731static int lp8788_charger_remove(struct platform_device *pdev)
 732{
 733        struct lp8788_charger *pchg = platform_get_drvdata(pdev);
 734
 735        flush_work(&pchg->charger_work);
 736        lp8788_irq_unregister(pdev, pchg);
 737        lp8788_psy_unregister(pchg);
 738        lp8788_release_adc_channel(pchg);
 739
 740        return 0;
 741}
 742
 743static struct platform_driver lp8788_charger_driver = {
 744        .probe = lp8788_charger_probe,
 745        .remove = lp8788_charger_remove,
 746        .driver = {
 747                .name = LP8788_DEV_CHARGER,
 748        },
 749};
 750module_platform_driver(lp8788_charger_driver);
 751
 752MODULE_DESCRIPTION("TI LP8788 Charger Driver");
 753MODULE_AUTHOR("Milo Kim");
 754MODULE_LICENSE("GPL");
 755MODULE_ALIAS("platform:lp8788-charger");
 756