0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/bits.h>
0011 #include <linux/iio/consumer.h>
0012 #include <linux/iio/types.h>
0013 #include <linux/interrupt.h>
0014 #include <linux/mfd/mp2629.h>
0015 #include <linux/module.h>
0016 #include <linux/mod_devicetable.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/power_supply.h>
0019 #include <linux/regmap.h>
0020
0021 #define MP2629_REG_INPUT_ILIM 0x00
0022 #define MP2629_REG_INPUT_VLIM 0x01
0023 #define MP2629_REG_CHARGE_CTRL 0x04
0024 #define MP2629_REG_CHARGE_ILIM 0x05
0025 #define MP2629_REG_PRECHARGE 0x06
0026 #define MP2629_REG_TERM_CURRENT 0x06
0027 #define MP2629_REG_CHARGE_VLIM 0x07
0028 #define MP2629_REG_TIMER_CTRL 0x08
0029 #define MP2629_REG_IMPEDANCE_COMP 0x09
0030 #define MP2629_REG_INTERRUPT 0x0b
0031 #define MP2629_REG_STATUS 0x0c
0032 #define MP2629_REG_FAULT 0x0d
0033
0034 #define MP2629_MASK_INPUT_TYPE GENMASK(7, 5)
0035 #define MP2629_MASK_CHARGE_TYPE GENMASK(4, 3)
0036 #define MP2629_MASK_CHARGE_CTRL GENMASK(5, 4)
0037 #define MP2629_MASK_WDOG_CTRL GENMASK(5, 4)
0038 #define MP2629_MASK_IMPEDANCE GENMASK(7, 4)
0039
0040 #define MP2629_INPUTSOURCE_CHANGE GENMASK(7, 5)
0041 #define MP2629_CHARGING_CHANGE GENMASK(4, 3)
0042 #define MP2629_FAULT_BATTERY BIT(3)
0043 #define MP2629_FAULT_THERMAL BIT(4)
0044 #define MP2629_FAULT_INPUT BIT(5)
0045 #define MP2629_FAULT_OTG BIT(6)
0046
0047 #define MP2629_MAX_BATT_CAPACITY 100
0048
0049 #define MP2629_PROPS(_idx, _min, _max, _step) \
0050 [_idx] = { \
0051 .min = _min, \
0052 .max = _max, \
0053 .step = _step, \
0054 }
0055
0056 enum mp2629_source_type {
0057 MP2629_SOURCE_TYPE_NO_INPUT,
0058 MP2629_SOURCE_TYPE_NON_STD,
0059 MP2629_SOURCE_TYPE_SDP,
0060 MP2629_SOURCE_TYPE_CDP,
0061 MP2629_SOURCE_TYPE_DCP,
0062 MP2629_SOURCE_TYPE_OTG = 7,
0063 };
0064
0065 enum mp2629_field {
0066 INPUT_ILIM,
0067 INPUT_VLIM,
0068 CHARGE_ILIM,
0069 CHARGE_VLIM,
0070 PRECHARGE,
0071 TERM_CURRENT,
0072 MP2629_MAX_FIELD
0073 };
0074
0075 struct mp2629_charger {
0076 struct device *dev;
0077 int status;
0078 int fault;
0079
0080 struct regmap *regmap;
0081 struct regmap_field *regmap_fields[MP2629_MAX_FIELD];
0082 struct mutex lock;
0083 struct power_supply *usb;
0084 struct power_supply *battery;
0085 struct iio_channel *iiochan[MP2629_ADC_CHAN_END];
0086 };
0087
0088 struct mp2629_prop {
0089 int reg;
0090 int mask;
0091 int min;
0092 int max;
0093 int step;
0094 int shift;
0095 };
0096
0097 static enum power_supply_usb_type mp2629_usb_types[] = {
0098 POWER_SUPPLY_USB_TYPE_SDP,
0099 POWER_SUPPLY_USB_TYPE_DCP,
0100 POWER_SUPPLY_USB_TYPE_CDP,
0101 POWER_SUPPLY_USB_TYPE_PD_DRP,
0102 POWER_SUPPLY_USB_TYPE_UNKNOWN
0103 };
0104
0105 static enum power_supply_property mp2629_charger_usb_props[] = {
0106 POWER_SUPPLY_PROP_ONLINE,
0107 POWER_SUPPLY_PROP_USB_TYPE,
0108 POWER_SUPPLY_PROP_VOLTAGE_NOW,
0109 POWER_SUPPLY_PROP_CURRENT_NOW,
0110 POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
0111 POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT,
0112 };
0113
0114 static enum power_supply_property mp2629_charger_bat_props[] = {
0115 POWER_SUPPLY_PROP_STATUS,
0116 POWER_SUPPLY_PROP_HEALTH,
0117 POWER_SUPPLY_PROP_CHARGE_TYPE,
0118 POWER_SUPPLY_PROP_VOLTAGE_NOW,
0119 POWER_SUPPLY_PROP_CURRENT_NOW,
0120 POWER_SUPPLY_PROP_CAPACITY,
0121 POWER_SUPPLY_PROP_PRECHARGE_CURRENT,
0122 POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT,
0123 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
0124 POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
0125 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
0126 POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
0127 };
0128
0129 static struct mp2629_prop props[] = {
0130 MP2629_PROPS(INPUT_ILIM, 100000, 3250000, 50000),
0131 MP2629_PROPS(INPUT_VLIM, 3800000, 5300000, 100000),
0132 MP2629_PROPS(CHARGE_ILIM, 320000, 4520000, 40000),
0133 MP2629_PROPS(CHARGE_VLIM, 3400000, 4670000, 10000),
0134 MP2629_PROPS(PRECHARGE, 120000, 720000, 40000),
0135 MP2629_PROPS(TERM_CURRENT, 80000, 680000, 40000),
0136 };
0137
0138 static const struct reg_field mp2629_reg_fields[] = {
0139 [INPUT_ILIM] = REG_FIELD(MP2629_REG_INPUT_ILIM, 0, 5),
0140 [INPUT_VLIM] = REG_FIELD(MP2629_REG_INPUT_VLIM, 0, 3),
0141 [CHARGE_ILIM] = REG_FIELD(MP2629_REG_CHARGE_ILIM, 0, 6),
0142 [CHARGE_VLIM] = REG_FIELD(MP2629_REG_CHARGE_VLIM, 1, 7),
0143 [PRECHARGE] = REG_FIELD(MP2629_REG_PRECHARGE, 4, 7),
0144 [TERM_CURRENT] = REG_FIELD(MP2629_REG_TERM_CURRENT, 0, 3),
0145 };
0146
0147 static char *adc_chan_name[] = {
0148 "mp2629-batt-volt",
0149 "mp2629-system-volt",
0150 "mp2629-input-volt",
0151 "mp2629-batt-current",
0152 "mp2629-input-current",
0153 };
0154
0155 static int mp2629_read_adc(struct mp2629_charger *charger,
0156 enum mp2629_adc_chan ch,
0157 union power_supply_propval *val)
0158 {
0159 int ret;
0160 int chval;
0161
0162 ret = iio_read_channel_processed(charger->iiochan[ch], &chval);
0163 if (ret)
0164 return ret;
0165
0166 val->intval = chval * 1000;
0167
0168 return 0;
0169 }
0170
0171 static int mp2629_get_prop(struct mp2629_charger *charger,
0172 enum mp2629_field fld,
0173 union power_supply_propval *val)
0174 {
0175 int ret;
0176 unsigned int rval;
0177
0178 ret = regmap_field_read(charger->regmap_fields[fld], &rval);
0179 if (ret)
0180 return ret;
0181
0182 val->intval = rval * props[fld].step + props[fld].min;
0183
0184 return 0;
0185 }
0186
0187 static int mp2629_set_prop(struct mp2629_charger *charger,
0188 enum mp2629_field fld,
0189 const union power_supply_propval *val)
0190 {
0191 unsigned int rval;
0192
0193 if (val->intval < props[fld].min || val->intval > props[fld].max)
0194 return -EINVAL;
0195
0196 rval = (val->intval - props[fld].min) / props[fld].step;
0197 return regmap_field_write(charger->regmap_fields[fld], rval);
0198 }
0199
0200 static int mp2629_get_battery_capacity(struct mp2629_charger *charger,
0201 union power_supply_propval *val)
0202 {
0203 union power_supply_propval vnow, vlim;
0204 int ret;
0205
0206 ret = mp2629_read_adc(charger, MP2629_BATT_VOLT, &vnow);
0207 if (ret)
0208 return ret;
0209
0210 ret = mp2629_get_prop(charger, CHARGE_VLIM, &vlim);
0211 if (ret)
0212 return ret;
0213
0214 val->intval = (vnow.intval * 100) / vlim.intval;
0215 val->intval = min(val->intval, MP2629_MAX_BATT_CAPACITY);
0216
0217 return 0;
0218 }
0219
0220 static int mp2629_charger_battery_get_prop(struct power_supply *psy,
0221 enum power_supply_property psp,
0222 union power_supply_propval *val)
0223 {
0224 struct mp2629_charger *charger = dev_get_drvdata(psy->dev.parent);
0225 unsigned int rval;
0226 int ret = 0;
0227
0228 switch (psp) {
0229 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
0230 ret = mp2629_read_adc(charger, MP2629_BATT_VOLT, val);
0231 break;
0232
0233 case POWER_SUPPLY_PROP_CURRENT_NOW:
0234 ret = mp2629_read_adc(charger, MP2629_BATT_CURRENT, val);
0235 break;
0236
0237 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
0238 val->intval = 4520000;
0239 break;
0240
0241 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
0242 val->intval = 4670000;
0243 break;
0244
0245 case POWER_SUPPLY_PROP_CAPACITY:
0246 ret = mp2629_get_battery_capacity(charger, val);
0247 break;
0248
0249 case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
0250 ret = mp2629_get_prop(charger, TERM_CURRENT, val);
0251 break;
0252
0253 case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:
0254 ret = mp2629_get_prop(charger, PRECHARGE, val);
0255 break;
0256
0257 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
0258 ret = mp2629_get_prop(charger, CHARGE_VLIM, val);
0259 break;
0260
0261 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
0262 ret = mp2629_get_prop(charger, CHARGE_ILIM, val);
0263 break;
0264
0265 case POWER_SUPPLY_PROP_HEALTH:
0266 if (!charger->fault)
0267 val->intval = POWER_SUPPLY_HEALTH_GOOD;
0268 if (MP2629_FAULT_BATTERY & charger->fault)
0269 val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
0270 else if (MP2629_FAULT_THERMAL & charger->fault)
0271 val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
0272 else if (MP2629_FAULT_INPUT & charger->fault)
0273 val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
0274 break;
0275
0276 case POWER_SUPPLY_PROP_STATUS:
0277 ret = regmap_read(charger->regmap, MP2629_REG_STATUS, &rval);
0278 if (ret)
0279 break;
0280
0281 rval = (rval & MP2629_MASK_CHARGE_TYPE) >> 3;
0282 switch (rval) {
0283 case 0x00:
0284 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
0285 break;
0286 case 0x01:
0287 case 0x10:
0288 val->intval = POWER_SUPPLY_STATUS_CHARGING;
0289 break;
0290 case 0x11:
0291 val->intval = POWER_SUPPLY_STATUS_FULL;
0292 }
0293 break;
0294
0295 case POWER_SUPPLY_PROP_CHARGE_TYPE:
0296 ret = regmap_read(charger->regmap, MP2629_REG_STATUS, &rval);
0297 if (ret)
0298 break;
0299
0300 rval = (rval & MP2629_MASK_CHARGE_TYPE) >> 3;
0301 switch (rval) {
0302 case 0x00:
0303 val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
0304 break;
0305 case 0x01:
0306 val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
0307 break;
0308 case 0x10:
0309 val->intval = POWER_SUPPLY_CHARGE_TYPE_STANDARD;
0310 break;
0311 default:
0312 val->intval = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
0313 }
0314 break;
0315
0316 default:
0317 return -EINVAL;
0318 }
0319
0320 return ret;
0321 }
0322
0323 static int mp2629_charger_battery_set_prop(struct power_supply *psy,
0324 enum power_supply_property psp,
0325 const union power_supply_propval *val)
0326 {
0327 struct mp2629_charger *charger = dev_get_drvdata(psy->dev.parent);
0328
0329 switch (psp) {
0330 case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
0331 return mp2629_set_prop(charger, TERM_CURRENT, val);
0332
0333 case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:
0334 return mp2629_set_prop(charger, PRECHARGE, val);
0335
0336 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
0337 return mp2629_set_prop(charger, CHARGE_VLIM, val);
0338
0339 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
0340 return mp2629_set_prop(charger, CHARGE_ILIM, val);
0341
0342 default:
0343 return -EINVAL;
0344 }
0345 }
0346
0347 static int mp2629_charger_usb_get_prop(struct power_supply *psy,
0348 enum power_supply_property psp,
0349 union power_supply_propval *val)
0350 {
0351 struct mp2629_charger *charger = dev_get_drvdata(psy->dev.parent);
0352 unsigned int rval;
0353 int ret;
0354
0355 switch (psp) {
0356 case POWER_SUPPLY_PROP_ONLINE:
0357 ret = regmap_read(charger->regmap, MP2629_REG_STATUS, &rval);
0358 if (ret)
0359 break;
0360
0361 val->intval = !!(rval & MP2629_MASK_INPUT_TYPE);
0362 break;
0363
0364 case POWER_SUPPLY_PROP_USB_TYPE:
0365 ret = regmap_read(charger->regmap, MP2629_REG_STATUS, &rval);
0366 if (ret)
0367 break;
0368
0369 rval = (rval & MP2629_MASK_INPUT_TYPE) >> 5;
0370 switch (rval) {
0371 case MP2629_SOURCE_TYPE_SDP:
0372 val->intval = POWER_SUPPLY_USB_TYPE_SDP;
0373 break;
0374 case MP2629_SOURCE_TYPE_CDP:
0375 val->intval = POWER_SUPPLY_USB_TYPE_CDP;
0376 break;
0377 case MP2629_SOURCE_TYPE_DCP:
0378 val->intval = POWER_SUPPLY_USB_TYPE_DCP;
0379 break;
0380 case MP2629_SOURCE_TYPE_OTG:
0381 val->intval = POWER_SUPPLY_USB_TYPE_PD_DRP;
0382 break;
0383 default:
0384 val->intval = POWER_SUPPLY_USB_TYPE_UNKNOWN;
0385 break;
0386 }
0387 break;
0388
0389 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
0390 ret = mp2629_read_adc(charger, MP2629_INPUT_VOLT, val);
0391 break;
0392
0393 case POWER_SUPPLY_PROP_CURRENT_NOW:
0394 ret = mp2629_read_adc(charger, MP2629_INPUT_CURRENT, val);
0395 break;
0396
0397 case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT:
0398 ret = mp2629_get_prop(charger, INPUT_VLIM, val);
0399 break;
0400
0401 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
0402 ret = mp2629_get_prop(charger, INPUT_ILIM, val);
0403 break;
0404
0405 default:
0406 return -EINVAL;
0407 }
0408
0409 return ret;
0410 }
0411
0412 static int mp2629_charger_usb_set_prop(struct power_supply *psy,
0413 enum power_supply_property psp,
0414 const union power_supply_propval *val)
0415 {
0416 struct mp2629_charger *charger = dev_get_drvdata(psy->dev.parent);
0417
0418 switch (psp) {
0419 case POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT:
0420 return mp2629_set_prop(charger, INPUT_VLIM, val);
0421
0422 case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
0423 return mp2629_set_prop(charger, INPUT_ILIM, val);
0424
0425 default:
0426 return -EINVAL;
0427 }
0428 }
0429
0430 static int mp2629_charger_battery_prop_writeable(struct power_supply *psy,
0431 enum power_supply_property psp)
0432 {
0433 return (psp == POWER_SUPPLY_PROP_PRECHARGE_CURRENT) ||
0434 (psp == POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT) ||
0435 (psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT) ||
0436 (psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE);
0437 }
0438
0439 static int mp2629_charger_usb_prop_writeable(struct power_supply *psy,
0440 enum power_supply_property psp)
0441 {
0442 return (psp == POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT) ||
0443 (psp == POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT);
0444 }
0445
0446 static irqreturn_t mp2629_irq_handler(int irq, void *dev_id)
0447 {
0448 struct mp2629_charger *charger = dev_id;
0449 unsigned int rval;
0450 int ret;
0451
0452 mutex_lock(&charger->lock);
0453
0454 ret = regmap_read(charger->regmap, MP2629_REG_FAULT, &rval);
0455 if (ret)
0456 goto unlock;
0457
0458 if (rval) {
0459 charger->fault = rval;
0460 if (MP2629_FAULT_BATTERY & rval)
0461 dev_err(charger->dev, "Battery fault OVP\n");
0462 else if (MP2629_FAULT_THERMAL & rval)
0463 dev_err(charger->dev, "Thermal shutdown fault\n");
0464 else if (MP2629_FAULT_INPUT & rval)
0465 dev_err(charger->dev, "no input or input OVP\n");
0466 else if (MP2629_FAULT_OTG & rval)
0467 dev_err(charger->dev, "VIN overloaded\n");
0468
0469 goto unlock;
0470 }
0471
0472 ret = regmap_read(charger->regmap, MP2629_REG_STATUS, &rval);
0473 if (ret)
0474 goto unlock;
0475
0476 if (rval & MP2629_INPUTSOURCE_CHANGE)
0477 power_supply_changed(charger->usb);
0478 else if (rval & MP2629_CHARGING_CHANGE)
0479 power_supply_changed(charger->battery);
0480
0481 unlock:
0482 mutex_unlock(&charger->lock);
0483
0484 return IRQ_HANDLED;
0485 }
0486
0487 static const struct power_supply_desc mp2629_usb_desc = {
0488 .name = "mp2629_usb",
0489 .type = POWER_SUPPLY_TYPE_USB,
0490 .usb_types = mp2629_usb_types,
0491 .num_usb_types = ARRAY_SIZE(mp2629_usb_types),
0492 .properties = mp2629_charger_usb_props,
0493 .num_properties = ARRAY_SIZE(mp2629_charger_usb_props),
0494 .get_property = mp2629_charger_usb_get_prop,
0495 .set_property = mp2629_charger_usb_set_prop,
0496 .property_is_writeable = mp2629_charger_usb_prop_writeable,
0497 };
0498
0499 static const struct power_supply_desc mp2629_battery_desc = {
0500 .name = "mp2629_battery",
0501 .type = POWER_SUPPLY_TYPE_BATTERY,
0502 .properties = mp2629_charger_bat_props,
0503 .num_properties = ARRAY_SIZE(mp2629_charger_bat_props),
0504 .get_property = mp2629_charger_battery_get_prop,
0505 .set_property = mp2629_charger_battery_set_prop,
0506 .property_is_writeable = mp2629_charger_battery_prop_writeable,
0507 };
0508
0509 static ssize_t batt_impedance_compensation_show(struct device *dev,
0510 struct device_attribute *attr,
0511 char *buf)
0512 {
0513 struct mp2629_charger *charger = dev_get_drvdata(dev->parent);
0514 unsigned int rval;
0515 int ret;
0516
0517 ret = regmap_read(charger->regmap, MP2629_REG_IMPEDANCE_COMP, &rval);
0518 if (ret)
0519 return ret;
0520
0521 rval = (rval >> 4) * 10;
0522 return sprintf(buf, "%d mohm\n", rval);
0523 }
0524
0525 static ssize_t batt_impedance_compensation_store(struct device *dev,
0526 struct device_attribute *attr,
0527 const char *buf,
0528 size_t count)
0529 {
0530 struct mp2629_charger *charger = dev_get_drvdata(dev->parent);
0531 unsigned int val;
0532 int ret;
0533
0534 ret = kstrtouint(buf, 10, &val);
0535 if (ret)
0536 return ret;
0537
0538 if (val > 140)
0539 return -ERANGE;
0540
0541
0542 val = val / 10;
0543 ret = regmap_update_bits(charger->regmap, MP2629_REG_IMPEDANCE_COMP,
0544 MP2629_MASK_IMPEDANCE, val << 4);
0545 if (ret)
0546 return ret;
0547
0548 return count;
0549 }
0550
0551 static DEVICE_ATTR_RW(batt_impedance_compensation);
0552
0553 static struct attribute *mp2629_charger_sysfs_attrs[] = {
0554 &dev_attr_batt_impedance_compensation.attr,
0555 NULL
0556 };
0557 ATTRIBUTE_GROUPS(mp2629_charger_sysfs);
0558
0559 static void mp2629_charger_disable(void *data)
0560 {
0561 struct mp2629_charger *charger = data;
0562
0563 regmap_update_bits(charger->regmap, MP2629_REG_CHARGE_CTRL,
0564 MP2629_MASK_CHARGE_CTRL, 0);
0565 }
0566
0567 static int mp2629_charger_probe(struct platform_device *pdev)
0568 {
0569 struct device *dev = &pdev->dev;
0570 struct mp2629_data *ddata = dev_get_drvdata(dev->parent);
0571 struct mp2629_charger *charger;
0572 struct power_supply_config psy_cfg = {};
0573 int ret, i, irq;
0574
0575 charger = devm_kzalloc(dev, sizeof(*charger), GFP_KERNEL);
0576 if (!charger)
0577 return -ENOMEM;
0578
0579 charger->regmap = ddata->regmap;
0580 charger->dev = dev;
0581 platform_set_drvdata(pdev, charger);
0582
0583 irq = platform_get_irq(to_platform_device(dev->parent), 0);
0584 if (irq < 0)
0585 return irq;
0586
0587 for (i = 0; i < MP2629_MAX_FIELD; i++) {
0588 charger->regmap_fields[i] = devm_regmap_field_alloc(dev,
0589 charger->regmap, mp2629_reg_fields[i]);
0590 if (IS_ERR(charger->regmap_fields[i])) {
0591 dev_err(dev, "regmap field alloc fail %d\n", i);
0592 return PTR_ERR(charger->regmap_fields[i]);
0593 }
0594 }
0595
0596 for (i = 0; i < MP2629_ADC_CHAN_END; i++) {
0597 charger->iiochan[i] = devm_iio_channel_get(dev,
0598 adc_chan_name[i]);
0599 if (IS_ERR(charger->iiochan[i])) {
0600 dev_err(dev, "iio chan get %s err\n", adc_chan_name[i]);
0601 return PTR_ERR(charger->iiochan[i]);
0602 }
0603 }
0604
0605 ret = devm_add_action_or_reset(dev, mp2629_charger_disable, charger);
0606 if (ret)
0607 return ret;
0608
0609 charger->usb = devm_power_supply_register(dev, &mp2629_usb_desc, NULL);
0610 if (IS_ERR(charger->usb)) {
0611 dev_err(dev, "power supply register usb failed\n");
0612 return PTR_ERR(charger->usb);
0613 }
0614
0615 psy_cfg.drv_data = charger;
0616 psy_cfg.attr_grp = mp2629_charger_sysfs_groups;
0617 charger->battery = devm_power_supply_register(dev,
0618 &mp2629_battery_desc, &psy_cfg);
0619 if (IS_ERR(charger->battery)) {
0620 dev_err(dev, "power supply register battery failed\n");
0621 return PTR_ERR(charger->battery);
0622 }
0623
0624 ret = regmap_update_bits(charger->regmap, MP2629_REG_CHARGE_CTRL,
0625 MP2629_MASK_CHARGE_CTRL, BIT(4));
0626 if (ret) {
0627 dev_err(dev, "enable charge fail: %d\n", ret);
0628 return ret;
0629 }
0630
0631 regmap_update_bits(charger->regmap, MP2629_REG_TIMER_CTRL,
0632 MP2629_MASK_WDOG_CTRL, 0);
0633
0634 mutex_init(&charger->lock);
0635
0636 ret = devm_request_threaded_irq(dev, irq, NULL, mp2629_irq_handler,
0637 IRQF_ONESHOT | IRQF_TRIGGER_RISING,
0638 "mp2629-charger", charger);
0639 if (ret) {
0640 dev_err(dev, "failed to request gpio IRQ\n");
0641 return ret;
0642 }
0643
0644 regmap_update_bits(charger->regmap, MP2629_REG_INTERRUPT,
0645 GENMASK(6, 5), BIT(6) | BIT(5));
0646
0647 return 0;
0648 }
0649
0650 static const struct of_device_id mp2629_charger_of_match[] = {
0651 { .compatible = "mps,mp2629_charger"},
0652 {}
0653 };
0654 MODULE_DEVICE_TABLE(of, mp2629_charger_of_match);
0655
0656 static struct platform_driver mp2629_charger_driver = {
0657 .driver = {
0658 .name = "mp2629_charger",
0659 .of_match_table = mp2629_charger_of_match,
0660 },
0661 .probe = mp2629_charger_probe,
0662 };
0663 module_platform_driver(mp2629_charger_driver);
0664
0665 MODULE_AUTHOR("Saravanan Sekar <sravanhome@gmail.com>");
0666 MODULE_DESCRIPTION("MP2629 Charger driver");
0667 MODULE_LICENSE("GPL");