root/drivers/power/supply/lp8788-charger.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. lp8788_is_charger_detected
  2. lp8788_charger_get_property
  3. lp8788_get_battery_status
  4. lp8788_get_battery_health
  5. lp8788_get_battery_present
  6. lp8788_get_vbatt_adc
  7. lp8788_get_battery_voltage
  8. lp8788_get_battery_capacity
  9. lp8788_get_battery_temperature
  10. lp8788_get_battery_charging_current
  11. lp8788_get_charging_termination_voltage
  12. lp8788_battery_get_property
  13. lp8788_is_valid_charger_register
  14. lp8788_update_charger_params
  15. lp8788_psy_unregister
  16. lp8788_charger_event
  17. lp8788_find_irq_id
  18. lp8788_charger_irq_thread
  19. lp8788_set_irqs
  20. lp8788_irq_register
  21. lp8788_irq_unregister
  22. lp8788_setup_adc_channel
  23. lp8788_release_adc_channel
  24. lp8788_show_charger_status
  25. lp8788_show_eoc_time
  26. lp8788_show_eoc_level
  27. lp8788_psy_register
  28. lp8788_charger_probe
  29. lp8788_charger_remove

   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 
  55 enum 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 
  69 enum lp8788_charger_adc_sel {
  70         LP8788_VBATT,
  71         LP8788_BATT_TEMP,
  72         LP8788_NUM_CHG_ADC,
  73 };
  74 
  75 enum 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  */
  85 struct 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  */
 102 struct 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 
 113 static char *battery_supplied_to[] = {
 114         LP8788_BATTERY_NAME,
 115 };
 116 
 117 static enum power_supply_property lp8788_charger_prop[] = {
 118         POWER_SUPPLY_PROP_ONLINE,
 119         POWER_SUPPLY_PROP_CURRENT_MAX,
 120 };
 121 
 122 static 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 
 133 static 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 
 143 static 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 
 166 static 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 
 199 static 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 
 219 static 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 
 233 static 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 
 243 static 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 
 249 static 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 
 287 static 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 
 307 static 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 
 320 static 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 
 332 static 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 
 360 static inline bool lp8788_is_valid_charger_register(u8 addr)
 361 {
 362         return addr >= LP8788_CHG_START && addr <= LP8788_CHG_END;
 363 }
 364 
 365 static 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 
 393 static 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 
 401 static 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 
 409 static void lp8788_psy_unregister(struct lp8788_charger *pchg)
 410 {
 411         power_supply_unregister(pchg->battery);
 412         power_supply_unregister(pchg->charger);
 413 }
 414 
 415 static 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 
 425 static 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 
 441 static 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 
 470 irq_handled:
 471         return IRQ_HANDLED;
 472 }
 473 
 474 static 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 
 514 err_free_irq:
 515         for (i = 0; i < pchg->num_irqs; i++)
 516                 free_irq(pchg->irqs[i].virq, pchg);
 517         return ret;
 518 }
 519 
 520 static 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 
 550 static 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 
 565 static 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 
 583 static 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 
 596 static 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 
 621 static 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 
 638 static 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 
 661 static DEVICE_ATTR(charger_status, S_IRUSR, lp8788_show_charger_status, NULL);
 662 static DEVICE_ATTR(eoc_time, S_IRUSR, lp8788_show_eoc_time, NULL);
 663 static DEVICE_ATTR(eoc_level, S_IRUSR, lp8788_show_eoc_level, NULL);
 664 
 665 static 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 
 672 ATTRIBUTE_GROUPS(lp8788_charger_sysfs);
 673 
 674 static 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 
 699 static 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 
 731 static 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 
 743 static 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 };
 750 module_platform_driver(lp8788_charger_driver);
 751 
 752 MODULE_DESCRIPTION("TI LP8788 Charger Driver");
 753 MODULE_AUTHOR("Milo Kim");
 754 MODULE_LICENSE("GPL");
 755 MODULE_ALIAS("platform:lp8788-charger");

/* [<][>][^][v][top][bottom][index][help] */