0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/module.h>
0013 #include <linux/err.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/power_supply.h>
0016 #include <linux/mfd/wm8350/supply.h>
0017 #include <linux/mfd/wm8350/core.h>
0018 #include <linux/mfd/wm8350/comparator.h>
0019
0020 static int wm8350_read_battery_uvolts(struct wm8350 *wm8350)
0021 {
0022 return wm8350_read_auxadc(wm8350, WM8350_AUXADC_BATT, 0, 0)
0023 * WM8350_AUX_COEFF;
0024 }
0025
0026 static int wm8350_read_line_uvolts(struct wm8350 *wm8350)
0027 {
0028 return wm8350_read_auxadc(wm8350, WM8350_AUXADC_LINE, 0, 0)
0029 * WM8350_AUX_COEFF;
0030 }
0031
0032 static int wm8350_read_usb_uvolts(struct wm8350 *wm8350)
0033 {
0034 return wm8350_read_auxadc(wm8350, WM8350_AUXADC_USB, 0, 0)
0035 * WM8350_AUX_COEFF;
0036 }
0037
0038 #define WM8350_BATT_SUPPLY 1
0039 #define WM8350_USB_SUPPLY 2
0040 #define WM8350_LINE_SUPPLY 4
0041
0042 static inline int wm8350_charge_time_min(struct wm8350 *wm8350, int min)
0043 {
0044 if (!wm8350->power.rev_g_coeff)
0045 return (((min - 30) / 15) & 0xf) << 8;
0046 else
0047 return (((min - 30) / 30) & 0xf) << 8;
0048 }
0049
0050 static int wm8350_get_supplies(struct wm8350 *wm8350)
0051 {
0052 u16 sm, ov, co, chrg;
0053 int supplies = 0;
0054
0055 sm = wm8350_reg_read(wm8350, WM8350_STATE_MACHINE_STATUS);
0056 ov = wm8350_reg_read(wm8350, WM8350_MISC_OVERRIDES);
0057 co = wm8350_reg_read(wm8350, WM8350_COMPARATOR_OVERRIDES);
0058 chrg = wm8350_reg_read(wm8350, WM8350_BATTERY_CHARGER_CONTROL_2);
0059
0060
0061 sm = (sm & WM8350_USB_SM_MASK) >> WM8350_USB_SM_SHIFT;
0062
0063
0064 chrg &= WM8350_CHG_ISEL_MASK;
0065
0066
0067
0068 if (((sm == WM8350_USB_SM_100_SLV) ||
0069 (sm == WM8350_USB_SM_500_SLV) ||
0070 (sm == WM8350_USB_SM_STDBY_SLV))
0071 && !(ov & WM8350_USB_LIMIT_OVRDE))
0072 supplies = WM8350_USB_SUPPLY;
0073 else if (((sm == WM8350_USB_SM_100_SLV) ||
0074 (sm == WM8350_USB_SM_500_SLV) ||
0075 (sm == WM8350_USB_SM_STDBY_SLV))
0076 && (ov & WM8350_USB_LIMIT_OVRDE) && (chrg == 0))
0077 supplies = WM8350_USB_SUPPLY | WM8350_BATT_SUPPLY;
0078 else if (co & WM8350_WALL_FB_OVRDE)
0079 supplies = WM8350_LINE_SUPPLY;
0080 else
0081 supplies = WM8350_BATT_SUPPLY;
0082
0083 return supplies;
0084 }
0085
0086 static int wm8350_charger_config(struct wm8350 *wm8350,
0087 struct wm8350_charger_policy *policy)
0088 {
0089 u16 reg, eoc_mA, fast_limit_mA;
0090
0091 if (!policy) {
0092 dev_warn(wm8350->dev,
0093 "No charger policy, charger not configured.\n");
0094 return -EINVAL;
0095 }
0096
0097
0098 if (policy->fast_limit_USB_mA > 500) {
0099 dev_err(wm8350->dev, "USB fast charge > 500mA\n");
0100 return -EINVAL;
0101 }
0102
0103 eoc_mA = WM8350_CHG_EOC_mA(policy->eoc_mA);
0104
0105 wm8350_reg_unlock(wm8350);
0106
0107 reg = wm8350_reg_read(wm8350, WM8350_BATTERY_CHARGER_CONTROL_1)
0108 & WM8350_CHG_ENA_R168;
0109 wm8350_reg_write(wm8350, WM8350_BATTERY_CHARGER_CONTROL_1,
0110 reg | eoc_mA | policy->trickle_start_mV |
0111 WM8350_CHG_TRICKLE_TEMP_CHOKE |
0112 WM8350_CHG_TRICKLE_USB_CHOKE |
0113 WM8350_CHG_FAST_USB_THROTTLE);
0114
0115 if (wm8350_get_supplies(wm8350) & WM8350_USB_SUPPLY) {
0116 fast_limit_mA =
0117 WM8350_CHG_FAST_LIMIT_mA(policy->fast_limit_USB_mA);
0118 wm8350_reg_write(wm8350, WM8350_BATTERY_CHARGER_CONTROL_2,
0119 policy->charge_mV | policy->trickle_charge_USB_mA |
0120 fast_limit_mA | wm8350_charge_time_min(wm8350,
0121 policy->charge_timeout));
0122
0123 } else {
0124 fast_limit_mA =
0125 WM8350_CHG_FAST_LIMIT_mA(policy->fast_limit_mA);
0126 wm8350_reg_write(wm8350, WM8350_BATTERY_CHARGER_CONTROL_2,
0127 policy->charge_mV | policy->trickle_charge_mA |
0128 fast_limit_mA | wm8350_charge_time_min(wm8350,
0129 policy->charge_timeout));
0130 }
0131
0132 wm8350_reg_lock(wm8350);
0133 return 0;
0134 }
0135
0136 static int wm8350_batt_status(struct wm8350 *wm8350)
0137 {
0138 u16 state;
0139
0140 state = wm8350_reg_read(wm8350, WM8350_BATTERY_CHARGER_CONTROL_2);
0141 state &= WM8350_CHG_STS_MASK;
0142
0143 switch (state) {
0144 case WM8350_CHG_STS_OFF:
0145 return POWER_SUPPLY_STATUS_DISCHARGING;
0146
0147 case WM8350_CHG_STS_TRICKLE:
0148 case WM8350_CHG_STS_FAST:
0149 return POWER_SUPPLY_STATUS_CHARGING;
0150
0151 default:
0152 return POWER_SUPPLY_STATUS_UNKNOWN;
0153 }
0154 }
0155
0156 static ssize_t charger_state_show(struct device *dev,
0157 struct device_attribute *attr, char *buf)
0158 {
0159 struct wm8350 *wm8350 = dev_get_drvdata(dev);
0160 char *charge;
0161 int state;
0162
0163 state = wm8350_reg_read(wm8350, WM8350_BATTERY_CHARGER_CONTROL_2) &
0164 WM8350_CHG_STS_MASK;
0165 switch (state) {
0166 case WM8350_CHG_STS_OFF:
0167 charge = "Charger Off";
0168 break;
0169 case WM8350_CHG_STS_TRICKLE:
0170 charge = "Trickle Charging";
0171 break;
0172 case WM8350_CHG_STS_FAST:
0173 charge = "Fast Charging";
0174 break;
0175 default:
0176 return 0;
0177 }
0178
0179 return sprintf(buf, "%s\n", charge);
0180 }
0181
0182 static DEVICE_ATTR_RO(charger_state);
0183
0184 static irqreturn_t wm8350_charger_handler(int irq, void *data)
0185 {
0186 struct wm8350 *wm8350 = data;
0187 struct wm8350_power *power = &wm8350->power;
0188 struct wm8350_charger_policy *policy = power->policy;
0189
0190 switch (irq - wm8350->irq_base) {
0191 case WM8350_IRQ_CHG_BAT_FAIL:
0192 dev_err(wm8350->dev, "battery failed\n");
0193 break;
0194 case WM8350_IRQ_CHG_TO:
0195 dev_err(wm8350->dev, "charger timeout\n");
0196 power_supply_changed(power->battery);
0197 break;
0198
0199 case WM8350_IRQ_CHG_BAT_HOT:
0200 case WM8350_IRQ_CHG_BAT_COLD:
0201 case WM8350_IRQ_CHG_START:
0202 case WM8350_IRQ_CHG_END:
0203 power_supply_changed(power->battery);
0204 break;
0205
0206 case WM8350_IRQ_CHG_FAST_RDY:
0207 dev_dbg(wm8350->dev, "fast charger ready\n");
0208 wm8350_charger_config(wm8350, policy);
0209 wm8350_reg_unlock(wm8350);
0210 wm8350_set_bits(wm8350, WM8350_BATTERY_CHARGER_CONTROL_1,
0211 WM8350_CHG_FAST);
0212 wm8350_reg_lock(wm8350);
0213 break;
0214
0215 case WM8350_IRQ_CHG_VBATT_LT_3P9:
0216 dev_warn(wm8350->dev, "battery < 3.9V\n");
0217 break;
0218 case WM8350_IRQ_CHG_VBATT_LT_3P1:
0219 dev_warn(wm8350->dev, "battery < 3.1V\n");
0220 break;
0221 case WM8350_IRQ_CHG_VBATT_LT_2P85:
0222 dev_warn(wm8350->dev, "battery < 2.85V\n");
0223 break;
0224
0225
0226
0227 case WM8350_IRQ_EXT_USB_FB:
0228 case WM8350_IRQ_EXT_WALL_FB:
0229 wm8350_charger_config(wm8350, policy);
0230 fallthrough;
0231 case WM8350_IRQ_EXT_BAT_FB:
0232 power_supply_changed(power->battery);
0233 power_supply_changed(power->usb);
0234 power_supply_changed(power->ac);
0235 break;
0236
0237 default:
0238 dev_err(wm8350->dev, "Unknown interrupt %d\n", irq);
0239 }
0240
0241 return IRQ_HANDLED;
0242 }
0243
0244
0245
0246
0247 static int wm8350_ac_get_prop(struct power_supply *psy,
0248 enum power_supply_property psp,
0249 union power_supply_propval *val)
0250 {
0251 struct wm8350 *wm8350 = dev_get_drvdata(psy->dev.parent);
0252 int ret = 0;
0253
0254 switch (psp) {
0255 case POWER_SUPPLY_PROP_ONLINE:
0256 val->intval = !!(wm8350_get_supplies(wm8350) &
0257 WM8350_LINE_SUPPLY);
0258 break;
0259 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
0260 val->intval = wm8350_read_line_uvolts(wm8350);
0261 break;
0262 default:
0263 ret = -EINVAL;
0264 break;
0265 }
0266 return ret;
0267 }
0268
0269 static enum power_supply_property wm8350_ac_props[] = {
0270 POWER_SUPPLY_PROP_ONLINE,
0271 POWER_SUPPLY_PROP_VOLTAGE_NOW,
0272 };
0273
0274
0275
0276
0277 static int wm8350_usb_get_prop(struct power_supply *psy,
0278 enum power_supply_property psp,
0279 union power_supply_propval *val)
0280 {
0281 struct wm8350 *wm8350 = dev_get_drvdata(psy->dev.parent);
0282 int ret = 0;
0283
0284 switch (psp) {
0285 case POWER_SUPPLY_PROP_ONLINE:
0286 val->intval = !!(wm8350_get_supplies(wm8350) &
0287 WM8350_USB_SUPPLY);
0288 break;
0289 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
0290 val->intval = wm8350_read_usb_uvolts(wm8350);
0291 break;
0292 default:
0293 ret = -EINVAL;
0294 break;
0295 }
0296 return ret;
0297 }
0298
0299 static enum power_supply_property wm8350_usb_props[] = {
0300 POWER_SUPPLY_PROP_ONLINE,
0301 POWER_SUPPLY_PROP_VOLTAGE_NOW,
0302 };
0303
0304
0305
0306
0307
0308 static int wm8350_bat_check_health(struct wm8350 *wm8350)
0309 {
0310 u16 reg;
0311
0312 if (wm8350_read_battery_uvolts(wm8350) < 2850000)
0313 return POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
0314
0315 reg = wm8350_reg_read(wm8350, WM8350_CHARGER_OVERRIDES);
0316 if (reg & WM8350_CHG_BATT_HOT_OVRDE)
0317 return POWER_SUPPLY_HEALTH_OVERHEAT;
0318
0319 if (reg & WM8350_CHG_BATT_COLD_OVRDE)
0320 return POWER_SUPPLY_HEALTH_COLD;
0321
0322 return POWER_SUPPLY_HEALTH_GOOD;
0323 }
0324
0325 static int wm8350_bat_get_charge_type(struct wm8350 *wm8350)
0326 {
0327 int state;
0328
0329 state = wm8350_reg_read(wm8350, WM8350_BATTERY_CHARGER_CONTROL_2) &
0330 WM8350_CHG_STS_MASK;
0331 switch (state) {
0332 case WM8350_CHG_STS_OFF:
0333 return POWER_SUPPLY_CHARGE_TYPE_NONE;
0334 case WM8350_CHG_STS_TRICKLE:
0335 return POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
0336 case WM8350_CHG_STS_FAST:
0337 return POWER_SUPPLY_CHARGE_TYPE_FAST;
0338 default:
0339 return POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
0340 }
0341 }
0342
0343 static int wm8350_bat_get_property(struct power_supply *psy,
0344 enum power_supply_property psp,
0345 union power_supply_propval *val)
0346 {
0347 struct wm8350 *wm8350 = dev_get_drvdata(psy->dev.parent);
0348 int ret = 0;
0349
0350 switch (psp) {
0351 case POWER_SUPPLY_PROP_STATUS:
0352 val->intval = wm8350_batt_status(wm8350);
0353 break;
0354 case POWER_SUPPLY_PROP_ONLINE:
0355 val->intval = !!(wm8350_get_supplies(wm8350) &
0356 WM8350_BATT_SUPPLY);
0357 break;
0358 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
0359 val->intval = wm8350_read_battery_uvolts(wm8350);
0360 break;
0361 case POWER_SUPPLY_PROP_HEALTH:
0362 val->intval = wm8350_bat_check_health(wm8350);
0363 break;
0364 case POWER_SUPPLY_PROP_CHARGE_TYPE:
0365 val->intval = wm8350_bat_get_charge_type(wm8350);
0366 break;
0367 default:
0368 ret = -EINVAL;
0369 break;
0370 }
0371
0372 return ret;
0373 }
0374
0375 static enum power_supply_property wm8350_bat_props[] = {
0376 POWER_SUPPLY_PROP_STATUS,
0377 POWER_SUPPLY_PROP_ONLINE,
0378 POWER_SUPPLY_PROP_VOLTAGE_NOW,
0379 POWER_SUPPLY_PROP_HEALTH,
0380 POWER_SUPPLY_PROP_CHARGE_TYPE,
0381 };
0382
0383 static const struct power_supply_desc wm8350_ac_desc = {
0384 .name = "wm8350-ac",
0385 .type = POWER_SUPPLY_TYPE_MAINS,
0386 .properties = wm8350_ac_props,
0387 .num_properties = ARRAY_SIZE(wm8350_ac_props),
0388 .get_property = wm8350_ac_get_prop,
0389 };
0390
0391 static const struct power_supply_desc wm8350_battery_desc = {
0392 .name = "wm8350-battery",
0393 .properties = wm8350_bat_props,
0394 .num_properties = ARRAY_SIZE(wm8350_bat_props),
0395 .get_property = wm8350_bat_get_property,
0396 .use_for_apm = 1,
0397 };
0398
0399 static const struct power_supply_desc wm8350_usb_desc = {
0400 .name = "wm8350-usb",
0401 .type = POWER_SUPPLY_TYPE_USB,
0402 .properties = wm8350_usb_props,
0403 .num_properties = ARRAY_SIZE(wm8350_usb_props),
0404 .get_property = wm8350_usb_get_prop,
0405 };
0406
0407
0408
0409
0410
0411 static int wm8350_init_charger(struct wm8350 *wm8350)
0412 {
0413 int ret;
0414
0415
0416 ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT,
0417 wm8350_charger_handler, 0, "Battery hot", wm8350);
0418 if (ret)
0419 goto err;
0420
0421 ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD,
0422 wm8350_charger_handler, 0, "Battery cold", wm8350);
0423 if (ret)
0424 goto free_chg_bat_hot;
0425
0426 ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL,
0427 wm8350_charger_handler, 0, "Battery fail", wm8350);
0428 if (ret)
0429 goto free_chg_bat_cold;
0430
0431 ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_TO,
0432 wm8350_charger_handler, 0,
0433 "Charger timeout", wm8350);
0434 if (ret)
0435 goto free_chg_bat_fail;
0436
0437 ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_END,
0438 wm8350_charger_handler, 0,
0439 "Charge end", wm8350);
0440 if (ret)
0441 goto free_chg_to;
0442
0443 ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_START,
0444 wm8350_charger_handler, 0,
0445 "Charge start", wm8350);
0446 if (ret)
0447 goto free_chg_end;
0448
0449 ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_FAST_RDY,
0450 wm8350_charger_handler, 0,
0451 "Fast charge ready", wm8350);
0452 if (ret)
0453 goto free_chg_start;
0454
0455 ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9,
0456 wm8350_charger_handler, 0,
0457 "Battery <3.9V", wm8350);
0458 if (ret)
0459 goto free_chg_fast_rdy;
0460
0461 ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1,
0462 wm8350_charger_handler, 0,
0463 "Battery <3.1V", wm8350);
0464 if (ret)
0465 goto free_chg_vbatt_lt_3p9;
0466
0467 ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85,
0468 wm8350_charger_handler, 0,
0469 "Battery <2.85V", wm8350);
0470 if (ret)
0471 goto free_chg_vbatt_lt_3p1;
0472
0473
0474 ret = wm8350_register_irq(wm8350, WM8350_IRQ_EXT_USB_FB,
0475 wm8350_charger_handler, 0, "USB", wm8350);
0476 if (ret)
0477 goto free_chg_vbatt_lt_2p85;
0478
0479 ret = wm8350_register_irq(wm8350, WM8350_IRQ_EXT_WALL_FB,
0480 wm8350_charger_handler, 0, "Wall", wm8350);
0481 if (ret)
0482 goto free_ext_usb_fb;
0483
0484 ret = wm8350_register_irq(wm8350, WM8350_IRQ_EXT_BAT_FB,
0485 wm8350_charger_handler, 0, "Battery", wm8350);
0486 if (ret)
0487 goto free_ext_wall_fb;
0488
0489 return 0;
0490
0491 free_ext_wall_fb:
0492 wm8350_free_irq(wm8350, WM8350_IRQ_EXT_WALL_FB, wm8350);
0493 free_ext_usb_fb:
0494 wm8350_free_irq(wm8350, WM8350_IRQ_EXT_USB_FB, wm8350);
0495 free_chg_vbatt_lt_2p85:
0496 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85, wm8350);
0497 free_chg_vbatt_lt_3p1:
0498 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1, wm8350);
0499 free_chg_vbatt_lt_3p9:
0500 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9, wm8350);
0501 free_chg_fast_rdy:
0502 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_FAST_RDY, wm8350);
0503 free_chg_start:
0504 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_START, wm8350);
0505 free_chg_end:
0506 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_END, wm8350);
0507 free_chg_to:
0508 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_TO, wm8350);
0509 free_chg_bat_fail:
0510 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL, wm8350);
0511 free_chg_bat_cold:
0512 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD, wm8350);
0513 free_chg_bat_hot:
0514 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT, wm8350);
0515 err:
0516 return ret;
0517 }
0518
0519 static void free_charger_irq(struct wm8350 *wm8350)
0520 {
0521 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT, wm8350);
0522 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD, wm8350);
0523 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL, wm8350);
0524 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_TO, wm8350);
0525 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_END, wm8350);
0526 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_START, wm8350);
0527 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_FAST_RDY, wm8350);
0528 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9, wm8350);
0529 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1, wm8350);
0530 wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85, wm8350);
0531 wm8350_free_irq(wm8350, WM8350_IRQ_EXT_USB_FB, wm8350);
0532 wm8350_free_irq(wm8350, WM8350_IRQ_EXT_WALL_FB, wm8350);
0533 wm8350_free_irq(wm8350, WM8350_IRQ_EXT_BAT_FB, wm8350);
0534 }
0535
0536 static int wm8350_power_probe(struct platform_device *pdev)
0537 {
0538 struct wm8350 *wm8350 = platform_get_drvdata(pdev);
0539 struct wm8350_power *power = &wm8350->power;
0540 struct wm8350_charger_policy *policy = power->policy;
0541 int ret;
0542
0543 power->ac = power_supply_register(&pdev->dev, &wm8350_ac_desc, NULL);
0544 if (IS_ERR(power->ac))
0545 return PTR_ERR(power->ac);
0546
0547 power->battery = power_supply_register(&pdev->dev, &wm8350_battery_desc,
0548 NULL);
0549 if (IS_ERR(power->battery)) {
0550 ret = PTR_ERR(power->battery);
0551 goto battery_failed;
0552 }
0553
0554 power->usb = power_supply_register(&pdev->dev, &wm8350_usb_desc, NULL);
0555 if (IS_ERR(power->usb)) {
0556 ret = PTR_ERR(power->usb);
0557 goto usb_failed;
0558 }
0559
0560 ret = device_create_file(&pdev->dev, &dev_attr_charger_state);
0561 if (ret < 0)
0562 dev_warn(wm8350->dev, "failed to add charge sysfs: %d\n", ret);
0563 ret = 0;
0564
0565 wm8350_init_charger(wm8350);
0566 if (wm8350_charger_config(wm8350, policy) == 0) {
0567 wm8350_reg_unlock(wm8350);
0568 wm8350_set_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CHG_ENA);
0569 wm8350_reg_lock(wm8350);
0570 }
0571
0572 return ret;
0573
0574 usb_failed:
0575 power_supply_unregister(power->battery);
0576 battery_failed:
0577 power_supply_unregister(power->ac);
0578
0579 return ret;
0580 }
0581
0582 static int wm8350_power_remove(struct platform_device *pdev)
0583 {
0584 struct wm8350 *wm8350 = platform_get_drvdata(pdev);
0585 struct wm8350_power *power = &wm8350->power;
0586
0587 free_charger_irq(wm8350);
0588 device_remove_file(&pdev->dev, &dev_attr_charger_state);
0589 power_supply_unregister(power->battery);
0590 power_supply_unregister(power->ac);
0591 power_supply_unregister(power->usb);
0592 return 0;
0593 }
0594
0595 static struct platform_driver wm8350_power_driver = {
0596 .probe = wm8350_power_probe,
0597 .remove = wm8350_power_remove,
0598 .driver = {
0599 .name = "wm8350-power",
0600 },
0601 };
0602
0603 module_platform_driver(wm8350_power_driver);
0604
0605 MODULE_LICENSE("GPL");
0606 MODULE_DESCRIPTION("Power supply driver for WM8350");
0607 MODULE_ALIAS("platform:wm8350-power");