0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/err.h>
0011 #include <linux/iio/consumer.h>
0012 #include <linux/interrupt.h>
0013 #include <linux/irqdomain.h>
0014 #include <linux/mfd/lp8788.h>
0015 #include <linux/module.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/power_supply.h>
0018 #include <linux/slab.h>
0019 #include <linux/workqueue.h>
0020
0021
0022 #define LP8788_CHG_STATUS 0x07
0023 #define LP8788_CHG_IDCIN 0x13
0024 #define LP8788_CHG_IBATT 0x14
0025 #define LP8788_CHG_VTERM 0x15
0026 #define LP8788_CHG_EOC 0x16
0027
0028
0029 #define LP8788_CHG_INPUT_STATE_M 0x03
0030 #define LP8788_CHG_STATE_M 0x3C
0031 #define LP8788_CHG_STATE_S 2
0032 #define LP8788_NO_BATT_M BIT(6)
0033 #define LP8788_BAD_BATT_M BIT(7)
0034 #define LP8788_CHG_IBATT_M 0x1F
0035 #define LP8788_CHG_VTERM_M 0x0F
0036 #define LP8788_CHG_EOC_LEVEL_M 0x30
0037 #define LP8788_CHG_EOC_LEVEL_S 4
0038 #define LP8788_CHG_EOC_TIME_M 0x0E
0039 #define LP8788_CHG_EOC_TIME_S 1
0040 #define LP8788_CHG_EOC_MODE_M BIT(0)
0041
0042 #define LP8788_CHARGER_NAME "charger"
0043 #define LP8788_BATTERY_NAME "main_batt"
0044
0045 #define LP8788_CHG_START 0x11
0046 #define LP8788_CHG_END 0x1C
0047
0048 #define LP8788_ISEL_MAX 23
0049 #define LP8788_ISEL_STEP 50
0050 #define LP8788_VTERM_MIN 4100
0051 #define LP8788_VTERM_STEP 25
0052 #define LP8788_MAX_BATT_CAPACITY 100
0053 #define LP8788_MAX_CHG_IRQS 11
0054
0055 enum lp8788_charging_state {
0056 LP8788_OFF,
0057 LP8788_WARM_UP,
0058 LP8788_LOW_INPUT = 0x3,
0059 LP8788_PRECHARGE,
0060 LP8788_CC,
0061 LP8788_CV,
0062 LP8788_MAINTENANCE,
0063 LP8788_BATTERY_FAULT,
0064 LP8788_SYSTEM_SUPPORT = 0xC,
0065 LP8788_HIGH_CURRENT = 0xF,
0066 LP8788_MAX_CHG_STATE,
0067 };
0068
0069 enum lp8788_charger_adc_sel {
0070 LP8788_VBATT,
0071 LP8788_BATT_TEMP,
0072 LP8788_NUM_CHG_ADC,
0073 };
0074
0075 enum lp8788_charger_input_state {
0076 LP8788_SYSTEM_SUPPLY = 1,
0077 LP8788_FULL_FUNCTION,
0078 };
0079
0080
0081
0082
0083
0084
0085 struct lp8788_chg_irq {
0086 enum lp8788_int_id which;
0087 int virq;
0088 };
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102 struct lp8788_charger {
0103 struct lp8788 *lp;
0104 struct power_supply *charger;
0105 struct power_supply *battery;
0106 struct work_struct charger_work;
0107 struct iio_channel *chan[LP8788_NUM_CHG_ADC];
0108 struct lp8788_chg_irq irqs[LP8788_MAX_CHG_IRQS];
0109 int num_irqs;
0110 struct lp8788_charger_platform_data *pdata;
0111 };
0112
0113 static char *battery_supplied_to[] = {
0114 LP8788_BATTERY_NAME,
0115 };
0116
0117 static enum power_supply_property lp8788_charger_prop[] = {
0118 POWER_SUPPLY_PROP_ONLINE,
0119 POWER_SUPPLY_PROP_CURRENT_MAX,
0120 };
0121
0122 static enum power_supply_property lp8788_battery_prop[] = {
0123 POWER_SUPPLY_PROP_STATUS,
0124 POWER_SUPPLY_PROP_HEALTH,
0125 POWER_SUPPLY_PROP_PRESENT,
0126 POWER_SUPPLY_PROP_VOLTAGE_NOW,
0127 POWER_SUPPLY_PROP_CAPACITY,
0128 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
0129 POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
0130 POWER_SUPPLY_PROP_TEMP,
0131 };
0132
0133 static bool lp8788_is_charger_detected(struct lp8788_charger *pchg)
0134 {
0135 u8 data;
0136
0137 lp8788_read_byte(pchg->lp, LP8788_CHG_STATUS, &data);
0138 data &= LP8788_CHG_INPUT_STATE_M;
0139
0140 return data == LP8788_SYSTEM_SUPPLY || data == LP8788_FULL_FUNCTION;
0141 }
0142
0143 static int lp8788_charger_get_property(struct power_supply *psy,
0144 enum power_supply_property psp,
0145 union power_supply_propval *val)
0146 {
0147 struct lp8788_charger *pchg = dev_get_drvdata(psy->dev.parent);
0148 u8 read;
0149
0150 switch (psp) {
0151 case POWER_SUPPLY_PROP_ONLINE:
0152 val->intval = lp8788_is_charger_detected(pchg);
0153 break;
0154 case POWER_SUPPLY_PROP_CURRENT_MAX:
0155 lp8788_read_byte(pchg->lp, LP8788_CHG_IDCIN, &read);
0156 val->intval = LP8788_ISEL_STEP *
0157 (min_t(int, read, LP8788_ISEL_MAX) + 1);
0158 break;
0159 default:
0160 return -EINVAL;
0161 }
0162
0163 return 0;
0164 }
0165
0166 static int lp8788_get_battery_status(struct lp8788_charger *pchg,
0167 union power_supply_propval *val)
0168 {
0169 enum lp8788_charging_state state;
0170 u8 data;
0171 int ret;
0172
0173 ret = lp8788_read_byte(pchg->lp, LP8788_CHG_STATUS, &data);
0174 if (ret)
0175 return ret;
0176
0177 state = (data & LP8788_CHG_STATE_M) >> LP8788_CHG_STATE_S;
0178 switch (state) {
0179 case LP8788_OFF:
0180 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
0181 break;
0182 case LP8788_PRECHARGE:
0183 case LP8788_CC:
0184 case LP8788_CV:
0185 case LP8788_HIGH_CURRENT:
0186 val->intval = POWER_SUPPLY_STATUS_CHARGING;
0187 break;
0188 case LP8788_MAINTENANCE:
0189 val->intval = POWER_SUPPLY_STATUS_FULL;
0190 break;
0191 default:
0192 val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
0193 break;
0194 }
0195
0196 return 0;
0197 }
0198
0199 static int lp8788_get_battery_health(struct lp8788_charger *pchg,
0200 union power_supply_propval *val)
0201 {
0202 u8 data;
0203 int ret;
0204
0205 ret = lp8788_read_byte(pchg->lp, LP8788_CHG_STATUS, &data);
0206 if (ret)
0207 return ret;
0208
0209 if (data & LP8788_NO_BATT_M)
0210 val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
0211 else if (data & LP8788_BAD_BATT_M)
0212 val->intval = POWER_SUPPLY_HEALTH_DEAD;
0213 else
0214 val->intval = POWER_SUPPLY_HEALTH_GOOD;
0215
0216 return 0;
0217 }
0218
0219 static int lp8788_get_battery_present(struct lp8788_charger *pchg,
0220 union power_supply_propval *val)
0221 {
0222 u8 data;
0223 int ret;
0224
0225 ret = lp8788_read_byte(pchg->lp, LP8788_CHG_STATUS, &data);
0226 if (ret)
0227 return ret;
0228
0229 val->intval = !(data & LP8788_NO_BATT_M);
0230 return 0;
0231 }
0232
0233 static int lp8788_get_vbatt_adc(struct lp8788_charger *pchg, int *result)
0234 {
0235 struct iio_channel *channel = pchg->chan[LP8788_VBATT];
0236
0237 if (!channel)
0238 return -EINVAL;
0239
0240 return iio_read_channel_processed(channel, result);
0241 }
0242
0243 static int lp8788_get_battery_voltage(struct lp8788_charger *pchg,
0244 union power_supply_propval *val)
0245 {
0246 return lp8788_get_vbatt_adc(pchg, &val->intval);
0247 }
0248
0249 static int lp8788_get_battery_capacity(struct lp8788_charger *pchg,
0250 union power_supply_propval *val)
0251 {
0252 struct lp8788 *lp = pchg->lp;
0253 struct lp8788_charger_platform_data *pdata = pchg->pdata;
0254 unsigned int max_vbatt;
0255 int vbatt;
0256 enum lp8788_charging_state state;
0257 u8 data;
0258 int ret;
0259
0260 if (!pdata)
0261 return -EINVAL;
0262
0263 max_vbatt = pdata->max_vbatt_mv;
0264 if (max_vbatt == 0)
0265 return -EINVAL;
0266
0267 ret = lp8788_read_byte(lp, LP8788_CHG_STATUS, &data);
0268 if (ret)
0269 return ret;
0270
0271 state = (data & LP8788_CHG_STATE_M) >> LP8788_CHG_STATE_S;
0272
0273 if (state == LP8788_MAINTENANCE) {
0274 val->intval = LP8788_MAX_BATT_CAPACITY;
0275 } else {
0276 ret = lp8788_get_vbatt_adc(pchg, &vbatt);
0277 if (ret)
0278 return ret;
0279
0280 val->intval = (vbatt * LP8788_MAX_BATT_CAPACITY) / max_vbatt;
0281 val->intval = min(val->intval, LP8788_MAX_BATT_CAPACITY);
0282 }
0283
0284 return 0;
0285 }
0286
0287 static int lp8788_get_battery_temperature(struct lp8788_charger *pchg,
0288 union power_supply_propval *val)
0289 {
0290 struct iio_channel *channel = pchg->chan[LP8788_BATT_TEMP];
0291 int result;
0292 int ret;
0293
0294 if (!channel)
0295 return -EINVAL;
0296
0297 ret = iio_read_channel_processed(channel, &result);
0298 if (ret < 0)
0299 return -EINVAL;
0300
0301
0302 val->intval = result * 10;
0303
0304 return 0;
0305 }
0306
0307 static int lp8788_get_battery_charging_current(struct lp8788_charger *pchg,
0308 union power_supply_propval *val)
0309 {
0310 u8 read;
0311
0312 lp8788_read_byte(pchg->lp, LP8788_CHG_IBATT, &read);
0313 read &= LP8788_CHG_IBATT_M;
0314 val->intval = LP8788_ISEL_STEP *
0315 (min_t(int, read, LP8788_ISEL_MAX) + 1);
0316
0317 return 0;
0318 }
0319
0320 static int lp8788_get_charging_termination_voltage(struct lp8788_charger *pchg,
0321 union power_supply_propval *val)
0322 {
0323 u8 read;
0324
0325 lp8788_read_byte(pchg->lp, LP8788_CHG_VTERM, &read);
0326 read &= LP8788_CHG_VTERM_M;
0327 val->intval = LP8788_VTERM_MIN + LP8788_VTERM_STEP * read;
0328
0329 return 0;
0330 }
0331
0332 static int lp8788_battery_get_property(struct power_supply *psy,
0333 enum power_supply_property psp,
0334 union power_supply_propval *val)
0335 {
0336 struct lp8788_charger *pchg = dev_get_drvdata(psy->dev.parent);
0337
0338 switch (psp) {
0339 case POWER_SUPPLY_PROP_STATUS:
0340 return lp8788_get_battery_status(pchg, val);
0341 case POWER_SUPPLY_PROP_HEALTH:
0342 return lp8788_get_battery_health(pchg, val);
0343 case POWER_SUPPLY_PROP_PRESENT:
0344 return lp8788_get_battery_present(pchg, val);
0345 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
0346 return lp8788_get_battery_voltage(pchg, val);
0347 case POWER_SUPPLY_PROP_CAPACITY:
0348 return lp8788_get_battery_capacity(pchg, val);
0349 case POWER_SUPPLY_PROP_TEMP:
0350 return lp8788_get_battery_temperature(pchg, val);
0351 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
0352 return lp8788_get_battery_charging_current(pchg, val);
0353 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
0354 return lp8788_get_charging_termination_voltage(pchg, val);
0355 default:
0356 return -EINVAL;
0357 }
0358 }
0359
0360 static inline bool lp8788_is_valid_charger_register(u8 addr)
0361 {
0362 return addr >= LP8788_CHG_START && addr <= LP8788_CHG_END;
0363 }
0364
0365 static int lp8788_update_charger_params(struct platform_device *pdev,
0366 struct lp8788_charger *pchg)
0367 {
0368 struct lp8788 *lp = pchg->lp;
0369 struct lp8788_charger_platform_data *pdata = pchg->pdata;
0370 struct lp8788_chg_param *param;
0371 int i;
0372 int ret;
0373
0374 if (!pdata || !pdata->chg_params) {
0375 dev_info(&pdev->dev, "skip updating charger parameters\n");
0376 return 0;
0377 }
0378
0379
0380 for (i = 0; i < pdata->num_chg_params; i++) {
0381 param = pdata->chg_params + i;
0382
0383 if (lp8788_is_valid_charger_register(param->addr)) {
0384 ret = lp8788_write_byte(lp, param->addr, param->val);
0385 if (ret)
0386 return ret;
0387 }
0388 }
0389
0390 return 0;
0391 }
0392
0393 static const struct power_supply_desc lp8788_psy_charger_desc = {
0394 .name = LP8788_CHARGER_NAME,
0395 .type = POWER_SUPPLY_TYPE_MAINS,
0396 .properties = lp8788_charger_prop,
0397 .num_properties = ARRAY_SIZE(lp8788_charger_prop),
0398 .get_property = lp8788_charger_get_property,
0399 };
0400
0401 static const struct power_supply_desc lp8788_psy_battery_desc = {
0402 .name = LP8788_BATTERY_NAME,
0403 .type = POWER_SUPPLY_TYPE_BATTERY,
0404 .properties = lp8788_battery_prop,
0405 .num_properties = ARRAY_SIZE(lp8788_battery_prop),
0406 .get_property = lp8788_battery_get_property,
0407 };
0408
0409 static void lp8788_psy_unregister(struct lp8788_charger *pchg)
0410 {
0411 power_supply_unregister(pchg->battery);
0412 power_supply_unregister(pchg->charger);
0413 }
0414
0415 static void lp8788_charger_event(struct work_struct *work)
0416 {
0417 struct lp8788_charger *pchg =
0418 container_of(work, struct lp8788_charger, charger_work);
0419 struct lp8788_charger_platform_data *pdata = pchg->pdata;
0420 enum lp8788_charger_event event = lp8788_is_charger_detected(pchg);
0421
0422 pdata->charger_event(pchg->lp, event);
0423 }
0424
0425 static bool lp8788_find_irq_id(struct lp8788_charger *pchg, int virq, int *id)
0426 {
0427 bool found = false;
0428 int i;
0429
0430 for (i = 0; i < pchg->num_irqs; i++) {
0431 if (pchg->irqs[i].virq == virq) {
0432 *id = pchg->irqs[i].which;
0433 found = true;
0434 break;
0435 }
0436 }
0437
0438 return found;
0439 }
0440
0441 static irqreturn_t lp8788_charger_irq_thread(int virq, void *ptr)
0442 {
0443 struct lp8788_charger *pchg = ptr;
0444 struct lp8788_charger_platform_data *pdata = pchg->pdata;
0445 int id = -1;
0446
0447 if (!lp8788_find_irq_id(pchg, virq, &id))
0448 return IRQ_NONE;
0449
0450 switch (id) {
0451 case LP8788_INT_CHG_INPUT_STATE:
0452 case LP8788_INT_CHG_STATE:
0453 case LP8788_INT_EOC:
0454 case LP8788_INT_BATT_LOW:
0455 case LP8788_INT_NO_BATT:
0456 power_supply_changed(pchg->charger);
0457 power_supply_changed(pchg->battery);
0458 break;
0459 default:
0460 break;
0461 }
0462
0463
0464 if (!pdata)
0465 goto irq_handled;
0466
0467 if (pdata->charger_event && id == LP8788_INT_CHG_INPUT_STATE)
0468 schedule_work(&pchg->charger_work);
0469
0470 irq_handled:
0471 return IRQ_HANDLED;
0472 }
0473
0474 static int lp8788_set_irqs(struct platform_device *pdev,
0475 struct lp8788_charger *pchg, const char *name)
0476 {
0477 struct resource *r;
0478 struct irq_domain *irqdm = pchg->lp->irqdm;
0479 int irq_start;
0480 int irq_end;
0481 int virq;
0482 int nr_irq;
0483 int i;
0484 int ret;
0485
0486
0487 r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, name);
0488 if (!r)
0489 return 0;
0490
0491 irq_start = r->start;
0492 irq_end = r->end;
0493
0494 for (i = irq_start; i <= irq_end; i++) {
0495 nr_irq = pchg->num_irqs;
0496
0497 virq = irq_create_mapping(irqdm, i);
0498 pchg->irqs[nr_irq].virq = virq;
0499 pchg->irqs[nr_irq].which = i;
0500 pchg->num_irqs++;
0501
0502 ret = request_threaded_irq(virq, NULL,
0503 lp8788_charger_irq_thread,
0504 IRQF_ONESHOT, name, pchg);
0505 if (ret)
0506 break;
0507 }
0508
0509 if (i <= irq_end)
0510 goto err_free_irq;
0511
0512 return 0;
0513
0514 err_free_irq:
0515 for (i = 0; i < pchg->num_irqs; i++)
0516 free_irq(pchg->irqs[i].virq, pchg);
0517 return ret;
0518 }
0519
0520 static int lp8788_irq_register(struct platform_device *pdev,
0521 struct lp8788_charger *pchg)
0522 {
0523 const char *name[] = {
0524 LP8788_CHG_IRQ, LP8788_PRSW_IRQ, LP8788_BATT_IRQ
0525 };
0526 int i;
0527 int ret;
0528
0529 INIT_WORK(&pchg->charger_work, lp8788_charger_event);
0530 pchg->num_irqs = 0;
0531
0532 for (i = 0; i < ARRAY_SIZE(name); i++) {
0533 ret = lp8788_set_irqs(pdev, pchg, name[i]);
0534 if (ret) {
0535 dev_warn(&pdev->dev, "irq setup failed: %s\n", name[i]);
0536 return ret;
0537 }
0538 }
0539
0540 if (pchg->num_irqs > LP8788_MAX_CHG_IRQS) {
0541 dev_err(&pdev->dev, "invalid total number of irqs: %d\n",
0542 pchg->num_irqs);
0543 return -EINVAL;
0544 }
0545
0546
0547 return 0;
0548 }
0549
0550 static void lp8788_irq_unregister(struct platform_device *pdev,
0551 struct lp8788_charger *pchg)
0552 {
0553 int i;
0554 int irq;
0555
0556 for (i = 0; i < pchg->num_irqs; i++) {
0557 irq = pchg->irqs[i].virq;
0558 if (!irq)
0559 continue;
0560
0561 free_irq(irq, pchg);
0562 }
0563 }
0564
0565 static void lp8788_setup_adc_channel(struct device *dev,
0566 struct lp8788_charger *pchg)
0567 {
0568 struct lp8788_charger_platform_data *pdata = pchg->pdata;
0569 struct iio_channel *chan;
0570
0571 if (!pdata)
0572 return;
0573
0574
0575 chan = devm_iio_channel_get(dev, pdata->adc_vbatt);
0576 pchg->chan[LP8788_VBATT] = IS_ERR(chan) ? NULL : chan;
0577
0578
0579 chan = devm_iio_channel_get(dev, pdata->adc_batt_temp);
0580 pchg->chan[LP8788_BATT_TEMP] = IS_ERR(chan) ? NULL : chan;
0581 }
0582
0583 static ssize_t lp8788_show_charger_status(struct device *dev,
0584 struct device_attribute *attr, char *buf)
0585 {
0586 struct lp8788_charger *pchg = dev_get_drvdata(dev);
0587 enum lp8788_charging_state state;
0588 static const char * const desc[LP8788_MAX_CHG_STATE] = {
0589 [LP8788_OFF] = "CHARGER OFF",
0590 [LP8788_WARM_UP] = "WARM UP",
0591 [LP8788_LOW_INPUT] = "LOW INPUT STATE",
0592 [LP8788_PRECHARGE] = "CHARGING - PRECHARGE",
0593 [LP8788_CC] = "CHARGING - CC",
0594 [LP8788_CV] = "CHARGING - CV",
0595 [LP8788_MAINTENANCE] = "NO CHARGING - MAINTENANCE",
0596 [LP8788_BATTERY_FAULT] = "BATTERY FAULT",
0597 [LP8788_SYSTEM_SUPPORT] = "SYSTEM SUPPORT",
0598 [LP8788_HIGH_CURRENT] = "HIGH CURRENT",
0599 };
0600 u8 data;
0601
0602 lp8788_read_byte(pchg->lp, LP8788_CHG_STATUS, &data);
0603 state = (data & LP8788_CHG_STATE_M) >> LP8788_CHG_STATE_S;
0604
0605 return scnprintf(buf, PAGE_SIZE, "%s\n", desc[state]);
0606 }
0607
0608 static ssize_t lp8788_show_eoc_time(struct device *dev,
0609 struct device_attribute *attr, char *buf)
0610 {
0611 struct lp8788_charger *pchg = dev_get_drvdata(dev);
0612 static const char * const stime[] = {
0613 "400ms", "5min", "10min", "15min",
0614 "20min", "25min", "30min", "No timeout"
0615 };
0616 u8 val;
0617
0618 lp8788_read_byte(pchg->lp, LP8788_CHG_EOC, &val);
0619 val = (val & LP8788_CHG_EOC_TIME_M) >> LP8788_CHG_EOC_TIME_S;
0620
0621 return scnprintf(buf, PAGE_SIZE, "End Of Charge Time: %s\n",
0622 stime[val]);
0623 }
0624
0625 static ssize_t lp8788_show_eoc_level(struct device *dev,
0626 struct device_attribute *attr, char *buf)
0627 {
0628 struct lp8788_charger *pchg = dev_get_drvdata(dev);
0629 static const char * const abs_level[] = {
0630 "25mA", "49mA", "75mA", "98mA"
0631 };
0632 static const char * const relative_level[] = {
0633 "5%", "10%", "15%", "20%"
0634 };
0635 const char *level;
0636 u8 val;
0637 u8 mode;
0638
0639 lp8788_read_byte(pchg->lp, LP8788_CHG_EOC, &val);
0640
0641 mode = val & LP8788_CHG_EOC_MODE_M;
0642 val = (val & LP8788_CHG_EOC_LEVEL_M) >> LP8788_CHG_EOC_LEVEL_S;
0643 level = mode ? abs_level[val] : relative_level[val];
0644
0645 return scnprintf(buf, PAGE_SIZE, "End Of Charge Level: %s\n", level);
0646 }
0647
0648 static DEVICE_ATTR(charger_status, S_IRUSR, lp8788_show_charger_status, NULL);
0649 static DEVICE_ATTR(eoc_time, S_IRUSR, lp8788_show_eoc_time, NULL);
0650 static DEVICE_ATTR(eoc_level, S_IRUSR, lp8788_show_eoc_level, NULL);
0651
0652 static struct attribute *lp8788_charger_sysfs_attrs[] = {
0653 &dev_attr_charger_status.attr,
0654 &dev_attr_eoc_time.attr,
0655 &dev_attr_eoc_level.attr,
0656 NULL,
0657 };
0658
0659 ATTRIBUTE_GROUPS(lp8788_charger_sysfs);
0660
0661 static int lp8788_psy_register(struct platform_device *pdev,
0662 struct lp8788_charger *pchg)
0663 {
0664 struct power_supply_config charger_cfg = {};
0665
0666 charger_cfg.attr_grp = lp8788_charger_sysfs_groups;
0667 charger_cfg.supplied_to = battery_supplied_to;
0668 charger_cfg.num_supplicants = ARRAY_SIZE(battery_supplied_to);
0669
0670 pchg->charger = power_supply_register(&pdev->dev,
0671 &lp8788_psy_charger_desc,
0672 &charger_cfg);
0673 if (IS_ERR(pchg->charger))
0674 return -EPERM;
0675
0676 pchg->battery = power_supply_register(&pdev->dev,
0677 &lp8788_psy_battery_desc, NULL);
0678 if (IS_ERR(pchg->battery)) {
0679 power_supply_unregister(pchg->charger);
0680 return -EPERM;
0681 }
0682
0683 return 0;
0684 }
0685
0686 static int lp8788_charger_probe(struct platform_device *pdev)
0687 {
0688 struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
0689 struct lp8788_charger *pchg;
0690 struct device *dev = &pdev->dev;
0691 int ret;
0692
0693 pchg = devm_kzalloc(dev, sizeof(struct lp8788_charger), GFP_KERNEL);
0694 if (!pchg)
0695 return -ENOMEM;
0696
0697 pchg->lp = lp;
0698 pchg->pdata = lp->pdata ? lp->pdata->chg_pdata : NULL;
0699 platform_set_drvdata(pdev, pchg);
0700
0701 ret = lp8788_update_charger_params(pdev, pchg);
0702 if (ret)
0703 return ret;
0704
0705 lp8788_setup_adc_channel(&pdev->dev, pchg);
0706
0707 ret = lp8788_psy_register(pdev, pchg);
0708 if (ret)
0709 return ret;
0710
0711 ret = lp8788_irq_register(pdev, pchg);
0712 if (ret)
0713 dev_warn(dev, "failed to register charger irq: %d\n", ret);
0714
0715 return 0;
0716 }
0717
0718 static int lp8788_charger_remove(struct platform_device *pdev)
0719 {
0720 struct lp8788_charger *pchg = platform_get_drvdata(pdev);
0721
0722 flush_work(&pchg->charger_work);
0723 lp8788_irq_unregister(pdev, pchg);
0724 lp8788_psy_unregister(pchg);
0725
0726 return 0;
0727 }
0728
0729 static struct platform_driver lp8788_charger_driver = {
0730 .probe = lp8788_charger_probe,
0731 .remove = lp8788_charger_remove,
0732 .driver = {
0733 .name = LP8788_DEV_CHARGER,
0734 },
0735 };
0736 module_platform_driver(lp8788_charger_driver);
0737
0738 MODULE_DESCRIPTION("TI LP8788 Charger Driver");
0739 MODULE_AUTHOR("Milo Kim");
0740 MODULE_LICENSE("GPL");
0741 MODULE_ALIAS("platform:lp8788-charger");