wm831x_power.c (19418B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * PMU driver for Wolfson Microelectronics wm831x PMICs 4 * 5 * Copyright 2009 Wolfson Microelectronics PLC. 6 */ 7 8#include <linux/module.h> 9#include <linux/err.h> 10#include <linux/platform_device.h> 11#include <linux/power_supply.h> 12#include <linux/slab.h> 13#include <linux/usb/phy.h> 14 15#include <linux/mfd/wm831x/core.h> 16#include <linux/mfd/wm831x/auxadc.h> 17#include <linux/mfd/wm831x/pmu.h> 18#include <linux/mfd/wm831x/pdata.h> 19 20struct wm831x_power { 21 struct wm831x *wm831x; 22 struct power_supply *wall; 23 struct power_supply *usb; 24 struct power_supply *battery; 25 struct power_supply_desc wall_desc; 26 struct power_supply_desc usb_desc; 27 struct power_supply_desc battery_desc; 28 char wall_name[20]; 29 char usb_name[20]; 30 char battery_name[20]; 31 bool have_battery; 32 struct usb_phy *usb_phy; 33 struct notifier_block usb_notify; 34}; 35 36static int wm831x_power_check_online(struct wm831x *wm831x, int supply, 37 union power_supply_propval *val) 38{ 39 int ret; 40 41 ret = wm831x_reg_read(wm831x, WM831X_SYSTEM_STATUS); 42 if (ret < 0) 43 return ret; 44 45 if (ret & supply) 46 val->intval = 1; 47 else 48 val->intval = 0; 49 50 return 0; 51} 52 53static int wm831x_power_read_voltage(struct wm831x *wm831x, 54 enum wm831x_auxadc src, 55 union power_supply_propval *val) 56{ 57 int ret; 58 59 ret = wm831x_auxadc_read_uv(wm831x, src); 60 if (ret >= 0) 61 val->intval = ret; 62 63 return ret; 64} 65 66/********************************************************************* 67 * WALL Power 68 *********************************************************************/ 69static int wm831x_wall_get_prop(struct power_supply *psy, 70 enum power_supply_property psp, 71 union power_supply_propval *val) 72{ 73 struct wm831x_power *wm831x_power = dev_get_drvdata(psy->dev.parent); 74 struct wm831x *wm831x = wm831x_power->wm831x; 75 int ret = 0; 76 77 switch (psp) { 78 case POWER_SUPPLY_PROP_ONLINE: 79 ret = wm831x_power_check_online(wm831x, WM831X_PWR_WALL, val); 80 break; 81 case POWER_SUPPLY_PROP_VOLTAGE_NOW: 82 ret = wm831x_power_read_voltage(wm831x, WM831X_AUX_WALL, val); 83 break; 84 default: 85 ret = -EINVAL; 86 break; 87 } 88 89 return ret; 90} 91 92static enum power_supply_property wm831x_wall_props[] = { 93 POWER_SUPPLY_PROP_ONLINE, 94 POWER_SUPPLY_PROP_VOLTAGE_NOW, 95}; 96 97/********************************************************************* 98 * USB Power 99 *********************************************************************/ 100static int wm831x_usb_get_prop(struct power_supply *psy, 101 enum power_supply_property psp, 102 union power_supply_propval *val) 103{ 104 struct wm831x_power *wm831x_power = dev_get_drvdata(psy->dev.parent); 105 struct wm831x *wm831x = wm831x_power->wm831x; 106 int ret = 0; 107 108 switch (psp) { 109 case POWER_SUPPLY_PROP_ONLINE: 110 ret = wm831x_power_check_online(wm831x, WM831X_PWR_USB, val); 111 break; 112 case POWER_SUPPLY_PROP_VOLTAGE_NOW: 113 ret = wm831x_power_read_voltage(wm831x, WM831X_AUX_USB, val); 114 break; 115 default: 116 ret = -EINVAL; 117 break; 118 } 119 120 return ret; 121} 122 123static enum power_supply_property wm831x_usb_props[] = { 124 POWER_SUPPLY_PROP_ONLINE, 125 POWER_SUPPLY_PROP_VOLTAGE_NOW, 126}; 127 128/* In milliamps */ 129static const unsigned int wm831x_usb_limits[] = { 130 0, 131 2, 132 100, 133 500, 134 900, 135 1500, 136 1800, 137 550, 138}; 139 140static int wm831x_usb_limit_change(struct notifier_block *nb, 141 unsigned long limit, void *data) 142{ 143 struct wm831x_power *wm831x_power = container_of(nb, 144 struct wm831x_power, 145 usb_notify); 146 unsigned int i, best; 147 148 /* Find the highest supported limit */ 149 best = 0; 150 for (i = 0; i < ARRAY_SIZE(wm831x_usb_limits); i++) { 151 if (limit >= wm831x_usb_limits[i] && 152 wm831x_usb_limits[best] < wm831x_usb_limits[i]) 153 best = i; 154 } 155 156 dev_dbg(wm831x_power->wm831x->dev, 157 "Limiting USB current to %umA", wm831x_usb_limits[best]); 158 159 wm831x_set_bits(wm831x_power->wm831x, WM831X_POWER_STATE, 160 WM831X_USB_ILIM_MASK, best); 161 162 return 0; 163} 164 165/********************************************************************* 166 * Battery properties 167 *********************************************************************/ 168 169struct chg_map { 170 int val; 171 int reg_val; 172}; 173 174static struct chg_map trickle_ilims[] = { 175 { 50, 0 << WM831X_CHG_TRKL_ILIM_SHIFT }, 176 { 100, 1 << WM831X_CHG_TRKL_ILIM_SHIFT }, 177 { 150, 2 << WM831X_CHG_TRKL_ILIM_SHIFT }, 178 { 200, 3 << WM831X_CHG_TRKL_ILIM_SHIFT }, 179}; 180 181static struct chg_map vsels[] = { 182 { 4050, 0 << WM831X_CHG_VSEL_SHIFT }, 183 { 4100, 1 << WM831X_CHG_VSEL_SHIFT }, 184 { 4150, 2 << WM831X_CHG_VSEL_SHIFT }, 185 { 4200, 3 << WM831X_CHG_VSEL_SHIFT }, 186}; 187 188static struct chg_map fast_ilims[] = { 189 { 0, 0 << WM831X_CHG_FAST_ILIM_SHIFT }, 190 { 50, 1 << WM831X_CHG_FAST_ILIM_SHIFT }, 191 { 100, 2 << WM831X_CHG_FAST_ILIM_SHIFT }, 192 { 150, 3 << WM831X_CHG_FAST_ILIM_SHIFT }, 193 { 200, 4 << WM831X_CHG_FAST_ILIM_SHIFT }, 194 { 250, 5 << WM831X_CHG_FAST_ILIM_SHIFT }, 195 { 300, 6 << WM831X_CHG_FAST_ILIM_SHIFT }, 196 { 350, 7 << WM831X_CHG_FAST_ILIM_SHIFT }, 197 { 400, 8 << WM831X_CHG_FAST_ILIM_SHIFT }, 198 { 450, 9 << WM831X_CHG_FAST_ILIM_SHIFT }, 199 { 500, 10 << WM831X_CHG_FAST_ILIM_SHIFT }, 200 { 600, 11 << WM831X_CHG_FAST_ILIM_SHIFT }, 201 { 700, 12 << WM831X_CHG_FAST_ILIM_SHIFT }, 202 { 800, 13 << WM831X_CHG_FAST_ILIM_SHIFT }, 203 { 900, 14 << WM831X_CHG_FAST_ILIM_SHIFT }, 204 { 1000, 15 << WM831X_CHG_FAST_ILIM_SHIFT }, 205}; 206 207static struct chg_map eoc_iterms[] = { 208 { 20, 0 << WM831X_CHG_ITERM_SHIFT }, 209 { 30, 1 << WM831X_CHG_ITERM_SHIFT }, 210 { 40, 2 << WM831X_CHG_ITERM_SHIFT }, 211 { 50, 3 << WM831X_CHG_ITERM_SHIFT }, 212 { 60, 4 << WM831X_CHG_ITERM_SHIFT }, 213 { 70, 5 << WM831X_CHG_ITERM_SHIFT }, 214 { 80, 6 << WM831X_CHG_ITERM_SHIFT }, 215 { 90, 7 << WM831X_CHG_ITERM_SHIFT }, 216}; 217 218static struct chg_map chg_times[] = { 219 { 60, 0 << WM831X_CHG_TIME_SHIFT }, 220 { 90, 1 << WM831X_CHG_TIME_SHIFT }, 221 { 120, 2 << WM831X_CHG_TIME_SHIFT }, 222 { 150, 3 << WM831X_CHG_TIME_SHIFT }, 223 { 180, 4 << WM831X_CHG_TIME_SHIFT }, 224 { 210, 5 << WM831X_CHG_TIME_SHIFT }, 225 { 240, 6 << WM831X_CHG_TIME_SHIFT }, 226 { 270, 7 << WM831X_CHG_TIME_SHIFT }, 227 { 300, 8 << WM831X_CHG_TIME_SHIFT }, 228 { 330, 9 << WM831X_CHG_TIME_SHIFT }, 229 { 360, 10 << WM831X_CHG_TIME_SHIFT }, 230 { 390, 11 << WM831X_CHG_TIME_SHIFT }, 231 { 420, 12 << WM831X_CHG_TIME_SHIFT }, 232 { 450, 13 << WM831X_CHG_TIME_SHIFT }, 233 { 480, 14 << WM831X_CHG_TIME_SHIFT }, 234 { 510, 15 << WM831X_CHG_TIME_SHIFT }, 235}; 236 237static void wm831x_battery_apply_config(struct wm831x *wm831x, 238 struct chg_map *map, int count, int val, 239 int *reg, const char *name, 240 const char *units) 241{ 242 int i; 243 244 for (i = 0; i < count; i++) 245 if (val == map[i].val) 246 break; 247 if (i == count) { 248 dev_err(wm831x->dev, "Invalid %s %d%s\n", 249 name, val, units); 250 } else { 251 *reg |= map[i].reg_val; 252 dev_dbg(wm831x->dev, "Set %s of %d%s\n", name, val, units); 253 } 254} 255 256static void wm831x_config_battery(struct wm831x *wm831x) 257{ 258 struct wm831x_pdata *wm831x_pdata = wm831x->dev->platform_data; 259 struct wm831x_battery_pdata *pdata; 260 int ret, reg1, reg2; 261 262 if (!wm831x_pdata || !wm831x_pdata->battery) { 263 dev_warn(wm831x->dev, 264 "No battery charger configuration\n"); 265 return; 266 } 267 268 pdata = wm831x_pdata->battery; 269 270 reg1 = 0; 271 reg2 = 0; 272 273 if (!pdata->enable) { 274 dev_info(wm831x->dev, "Battery charger disabled\n"); 275 return; 276 } 277 278 reg1 |= WM831X_CHG_ENA; 279 if (pdata->off_mask) 280 reg2 |= WM831X_CHG_OFF_MSK; 281 if (pdata->fast_enable) 282 reg1 |= WM831X_CHG_FAST; 283 284 wm831x_battery_apply_config(wm831x, trickle_ilims, 285 ARRAY_SIZE(trickle_ilims), 286 pdata->trickle_ilim, ®2, 287 "trickle charge current limit", "mA"); 288 289 wm831x_battery_apply_config(wm831x, vsels, ARRAY_SIZE(vsels), 290 pdata->vsel, ®2, 291 "target voltage", "mV"); 292 293 wm831x_battery_apply_config(wm831x, fast_ilims, ARRAY_SIZE(fast_ilims), 294 pdata->fast_ilim, ®2, 295 "fast charge current limit", "mA"); 296 297 wm831x_battery_apply_config(wm831x, eoc_iterms, ARRAY_SIZE(eoc_iterms), 298 pdata->eoc_iterm, ®1, 299 "end of charge current threshold", "mA"); 300 301 wm831x_battery_apply_config(wm831x, chg_times, ARRAY_SIZE(chg_times), 302 pdata->timeout, ®2, 303 "charger timeout", "min"); 304 305 ret = wm831x_reg_unlock(wm831x); 306 if (ret != 0) { 307 dev_err(wm831x->dev, "Failed to unlock registers: %d\n", ret); 308 return; 309 } 310 311 ret = wm831x_set_bits(wm831x, WM831X_CHARGER_CONTROL_1, 312 WM831X_CHG_ENA_MASK | 313 WM831X_CHG_FAST_MASK | 314 WM831X_CHG_ITERM_MASK, 315 reg1); 316 if (ret != 0) 317 dev_err(wm831x->dev, "Failed to set charger control 1: %d\n", 318 ret); 319 320 ret = wm831x_set_bits(wm831x, WM831X_CHARGER_CONTROL_2, 321 WM831X_CHG_OFF_MSK | 322 WM831X_CHG_TIME_MASK | 323 WM831X_CHG_FAST_ILIM_MASK | 324 WM831X_CHG_TRKL_ILIM_MASK | 325 WM831X_CHG_VSEL_MASK, 326 reg2); 327 if (ret != 0) 328 dev_err(wm831x->dev, "Failed to set charger control 2: %d\n", 329 ret); 330 331 wm831x_reg_lock(wm831x); 332} 333 334static int wm831x_bat_check_status(struct wm831x *wm831x, int *status) 335{ 336 int ret; 337 338 ret = wm831x_reg_read(wm831x, WM831X_SYSTEM_STATUS); 339 if (ret < 0) 340 return ret; 341 342 if (ret & WM831X_PWR_SRC_BATT) { 343 *status = POWER_SUPPLY_STATUS_DISCHARGING; 344 return 0; 345 } 346 347 ret = wm831x_reg_read(wm831x, WM831X_CHARGER_STATUS); 348 if (ret < 0) 349 return ret; 350 351 switch (ret & WM831X_CHG_STATE_MASK) { 352 case WM831X_CHG_STATE_OFF: 353 *status = POWER_SUPPLY_STATUS_NOT_CHARGING; 354 break; 355 case WM831X_CHG_STATE_TRICKLE: 356 case WM831X_CHG_STATE_FAST: 357 *status = POWER_SUPPLY_STATUS_CHARGING; 358 break; 359 360 default: 361 *status = POWER_SUPPLY_STATUS_UNKNOWN; 362 break; 363 } 364 365 return 0; 366} 367 368static int wm831x_bat_check_type(struct wm831x *wm831x, int *type) 369{ 370 int ret; 371 372 ret = wm831x_reg_read(wm831x, WM831X_CHARGER_STATUS); 373 if (ret < 0) 374 return ret; 375 376 switch (ret & WM831X_CHG_STATE_MASK) { 377 case WM831X_CHG_STATE_TRICKLE: 378 case WM831X_CHG_STATE_TRICKLE_OT: 379 *type = POWER_SUPPLY_CHARGE_TYPE_TRICKLE; 380 break; 381 case WM831X_CHG_STATE_FAST: 382 case WM831X_CHG_STATE_FAST_OT: 383 *type = POWER_SUPPLY_CHARGE_TYPE_FAST; 384 break; 385 default: 386 *type = POWER_SUPPLY_CHARGE_TYPE_NONE; 387 break; 388 } 389 390 return 0; 391} 392 393static int wm831x_bat_check_health(struct wm831x *wm831x, int *health) 394{ 395 int ret; 396 397 ret = wm831x_reg_read(wm831x, WM831X_CHARGER_STATUS); 398 if (ret < 0) 399 return ret; 400 401 if (ret & WM831X_BATT_HOT_STS) { 402 *health = POWER_SUPPLY_HEALTH_OVERHEAT; 403 return 0; 404 } 405 406 if (ret & WM831X_BATT_COLD_STS) { 407 *health = POWER_SUPPLY_HEALTH_COLD; 408 return 0; 409 } 410 411 if (ret & WM831X_BATT_OV_STS) { 412 *health = POWER_SUPPLY_HEALTH_OVERVOLTAGE; 413 return 0; 414 } 415 416 switch (ret & WM831X_CHG_STATE_MASK) { 417 case WM831X_CHG_STATE_TRICKLE_OT: 418 case WM831X_CHG_STATE_FAST_OT: 419 *health = POWER_SUPPLY_HEALTH_OVERHEAT; 420 break; 421 case WM831X_CHG_STATE_DEFECTIVE: 422 *health = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; 423 break; 424 default: 425 *health = POWER_SUPPLY_HEALTH_GOOD; 426 break; 427 } 428 429 return 0; 430} 431 432static int wm831x_bat_get_prop(struct power_supply *psy, 433 enum power_supply_property psp, 434 union power_supply_propval *val) 435{ 436 struct wm831x_power *wm831x_power = dev_get_drvdata(psy->dev.parent); 437 struct wm831x *wm831x = wm831x_power->wm831x; 438 int ret = 0; 439 440 switch (psp) { 441 case POWER_SUPPLY_PROP_STATUS: 442 ret = wm831x_bat_check_status(wm831x, &val->intval); 443 break; 444 case POWER_SUPPLY_PROP_ONLINE: 445 ret = wm831x_power_check_online(wm831x, WM831X_PWR_SRC_BATT, 446 val); 447 break; 448 case POWER_SUPPLY_PROP_VOLTAGE_NOW: 449 ret = wm831x_power_read_voltage(wm831x, WM831X_AUX_BATT, val); 450 break; 451 case POWER_SUPPLY_PROP_HEALTH: 452 ret = wm831x_bat_check_health(wm831x, &val->intval); 453 break; 454 case POWER_SUPPLY_PROP_CHARGE_TYPE: 455 ret = wm831x_bat_check_type(wm831x, &val->intval); 456 break; 457 default: 458 ret = -EINVAL; 459 break; 460 } 461 462 return ret; 463} 464 465static enum power_supply_property wm831x_bat_props[] = { 466 POWER_SUPPLY_PROP_STATUS, 467 POWER_SUPPLY_PROP_ONLINE, 468 POWER_SUPPLY_PROP_VOLTAGE_NOW, 469 POWER_SUPPLY_PROP_HEALTH, 470 POWER_SUPPLY_PROP_CHARGE_TYPE, 471}; 472 473static const char *wm831x_bat_irqs[] = { 474 "BATT HOT", 475 "BATT COLD", 476 "BATT FAIL", 477 "OV", 478 "END", 479 "TO", 480 "MODE", 481 "START", 482}; 483 484static irqreturn_t wm831x_bat_irq(int irq, void *data) 485{ 486 struct wm831x_power *wm831x_power = data; 487 struct wm831x *wm831x = wm831x_power->wm831x; 488 489 dev_dbg(wm831x->dev, "Battery status changed: %d\n", irq); 490 491 /* The battery charger is autonomous so we don't need to do 492 * anything except kick user space */ 493 if (wm831x_power->have_battery) 494 power_supply_changed(wm831x_power->battery); 495 496 return IRQ_HANDLED; 497} 498 499 500/********************************************************************* 501 * Initialisation 502 *********************************************************************/ 503 504static irqreturn_t wm831x_syslo_irq(int irq, void *data) 505{ 506 struct wm831x_power *wm831x_power = data; 507 struct wm831x *wm831x = wm831x_power->wm831x; 508 509 /* Not much we can actually *do* but tell people for 510 * posterity, we're probably about to run out of power. */ 511 dev_crit(wm831x->dev, "SYSVDD under voltage\n"); 512 513 return IRQ_HANDLED; 514} 515 516static irqreturn_t wm831x_pwr_src_irq(int irq, void *data) 517{ 518 struct wm831x_power *wm831x_power = data; 519 struct wm831x *wm831x = wm831x_power->wm831x; 520 521 dev_dbg(wm831x->dev, "Power source changed\n"); 522 523 /* Just notify for everything - little harm in overnotifying. */ 524 if (wm831x_power->have_battery) 525 power_supply_changed(wm831x_power->battery); 526 power_supply_changed(wm831x_power->usb); 527 power_supply_changed(wm831x_power->wall); 528 529 return IRQ_HANDLED; 530} 531 532static int wm831x_power_probe(struct platform_device *pdev) 533{ 534 struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); 535 struct wm831x_pdata *wm831x_pdata = wm831x->dev->platform_data; 536 struct wm831x_power *power; 537 int ret, irq, i; 538 539 power = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_power), 540 GFP_KERNEL); 541 if (power == NULL) 542 return -ENOMEM; 543 544 power->wm831x = wm831x; 545 platform_set_drvdata(pdev, power); 546 547 if (wm831x_pdata && wm831x_pdata->wm831x_num) { 548 snprintf(power->wall_name, sizeof(power->wall_name), 549 "wm831x-wall.%d", wm831x_pdata->wm831x_num); 550 snprintf(power->battery_name, sizeof(power->wall_name), 551 "wm831x-battery.%d", wm831x_pdata->wm831x_num); 552 snprintf(power->usb_name, sizeof(power->wall_name), 553 "wm831x-usb.%d", wm831x_pdata->wm831x_num); 554 } else { 555 snprintf(power->wall_name, sizeof(power->wall_name), 556 "wm831x-wall"); 557 snprintf(power->battery_name, sizeof(power->wall_name), 558 "wm831x-battery"); 559 snprintf(power->usb_name, sizeof(power->wall_name), 560 "wm831x-usb"); 561 } 562 563 /* We ignore configuration failures since we can still read back 564 * the status without enabling the charger. 565 */ 566 wm831x_config_battery(wm831x); 567 568 power->wall_desc.name = power->wall_name; 569 power->wall_desc.type = POWER_SUPPLY_TYPE_MAINS; 570 power->wall_desc.properties = wm831x_wall_props; 571 power->wall_desc.num_properties = ARRAY_SIZE(wm831x_wall_props); 572 power->wall_desc.get_property = wm831x_wall_get_prop; 573 power->wall = power_supply_register(&pdev->dev, &power->wall_desc, 574 NULL); 575 if (IS_ERR(power->wall)) { 576 ret = PTR_ERR(power->wall); 577 goto err; 578 } 579 580 power->usb_desc.name = power->usb_name, 581 power->usb_desc.type = POWER_SUPPLY_TYPE_USB; 582 power->usb_desc.properties = wm831x_usb_props; 583 power->usb_desc.num_properties = ARRAY_SIZE(wm831x_usb_props); 584 power->usb_desc.get_property = wm831x_usb_get_prop; 585 power->usb = power_supply_register(&pdev->dev, &power->usb_desc, NULL); 586 if (IS_ERR(power->usb)) { 587 ret = PTR_ERR(power->usb); 588 goto err_wall; 589 } 590 591 ret = wm831x_reg_read(wm831x, WM831X_CHARGER_CONTROL_1); 592 if (ret < 0) 593 goto err_wall; 594 power->have_battery = ret & WM831X_CHG_ENA; 595 596 if (power->have_battery) { 597 power->battery_desc.name = power->battery_name; 598 power->battery_desc.properties = wm831x_bat_props; 599 power->battery_desc.num_properties = ARRAY_SIZE(wm831x_bat_props); 600 power->battery_desc.get_property = wm831x_bat_get_prop; 601 power->battery_desc.use_for_apm = 1; 602 power->battery = power_supply_register(&pdev->dev, 603 &power->battery_desc, 604 NULL); 605 if (IS_ERR(power->battery)) { 606 ret = PTR_ERR(power->battery); 607 goto err_usb; 608 } 609 } 610 611 irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "SYSLO")); 612 ret = request_threaded_irq(irq, NULL, wm831x_syslo_irq, 613 IRQF_TRIGGER_RISING | IRQF_ONESHOT, "System power low", 614 power); 615 if (ret != 0) { 616 dev_err(&pdev->dev, "Failed to request SYSLO IRQ %d: %d\n", 617 irq, ret); 618 goto err_battery; 619 } 620 621 irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "PWR SRC")); 622 ret = request_threaded_irq(irq, NULL, wm831x_pwr_src_irq, 623 IRQF_TRIGGER_RISING | IRQF_ONESHOT, "Power source", 624 power); 625 if (ret != 0) { 626 dev_err(&pdev->dev, "Failed to request PWR SRC IRQ %d: %d\n", 627 irq, ret); 628 goto err_syslo; 629 } 630 631 for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) { 632 irq = wm831x_irq(wm831x, 633 platform_get_irq_byname(pdev, 634 wm831x_bat_irqs[i])); 635 ret = request_threaded_irq(irq, NULL, wm831x_bat_irq, 636 IRQF_TRIGGER_RISING | IRQF_ONESHOT, 637 wm831x_bat_irqs[i], 638 power); 639 if (ret != 0) { 640 dev_err(&pdev->dev, 641 "Failed to request %s IRQ %d: %d\n", 642 wm831x_bat_irqs[i], irq, ret); 643 goto err_bat_irq; 644 } 645 } 646 647 power->usb_phy = devm_usb_get_phy_by_phandle(&pdev->dev, "phys", 0); 648 ret = PTR_ERR_OR_ZERO(power->usb_phy); 649 650 switch (ret) { 651 case 0: 652 power->usb_notify.notifier_call = wm831x_usb_limit_change; 653 ret = usb_register_notifier(power->usb_phy, &power->usb_notify); 654 if (ret) { 655 dev_err(&pdev->dev, "Failed to register notifier: %d\n", 656 ret); 657 goto err_bat_irq; 658 } 659 break; 660 case -EINVAL: 661 case -ENODEV: 662 /* ignore missing usb-phy, it's optional */ 663 power->usb_phy = NULL; 664 ret = 0; 665 break; 666 default: 667 dev_err(&pdev->dev, "Failed to find USB phy: %d\n", ret); 668 fallthrough; 669 case -EPROBE_DEFER: 670 goto err_bat_irq; 671 } 672 673 return ret; 674 675err_bat_irq: 676 --i; 677 for (; i >= 0; i--) { 678 irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]); 679 free_irq(irq, power); 680 } 681 irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "PWR SRC")); 682 free_irq(irq, power); 683err_syslo: 684 irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "SYSLO")); 685 free_irq(irq, power); 686err_battery: 687 if (power->have_battery) 688 power_supply_unregister(power->battery); 689err_usb: 690 power_supply_unregister(power->usb); 691err_wall: 692 power_supply_unregister(power->wall); 693err: 694 return ret; 695} 696 697static int wm831x_power_remove(struct platform_device *pdev) 698{ 699 struct wm831x_power *wm831x_power = platform_get_drvdata(pdev); 700 struct wm831x *wm831x = wm831x_power->wm831x; 701 int irq, i; 702 703 if (wm831x_power->usb_phy) { 704 usb_unregister_notifier(wm831x_power->usb_phy, 705 &wm831x_power->usb_notify); 706 } 707 708 for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) { 709 irq = wm831x_irq(wm831x, 710 platform_get_irq_byname(pdev, 711 wm831x_bat_irqs[i])); 712 free_irq(irq, wm831x_power); 713 } 714 715 irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "PWR SRC")); 716 free_irq(irq, wm831x_power); 717 718 irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "SYSLO")); 719 free_irq(irq, wm831x_power); 720 721 if (wm831x_power->have_battery) 722 power_supply_unregister(wm831x_power->battery); 723 power_supply_unregister(wm831x_power->wall); 724 power_supply_unregister(wm831x_power->usb); 725 return 0; 726} 727 728static struct platform_driver wm831x_power_driver = { 729 .probe = wm831x_power_probe, 730 .remove = wm831x_power_remove, 731 .driver = { 732 .name = "wm831x-power", 733 }, 734}; 735 736module_platform_driver(wm831x_power_driver); 737 738MODULE_DESCRIPTION("Power supply driver for WM831x PMICs"); 739MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 740MODULE_LICENSE("GPL"); 741MODULE_ALIAS("platform:wm831x-power");