linux/drivers/power/supply/wm831x_power.c
<<
>>
Prefs
   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_battey_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_battey_apply_config(wm831x, trickle_ilims,
 285                                   ARRAY_SIZE(trickle_ilims),
 286                                   pdata->trickle_ilim, &reg2,
 287                                   "trickle charge current limit", "mA");
 288
 289        wm831x_battey_apply_config(wm831x, vsels, ARRAY_SIZE(vsels),
 290                                   pdata->vsel, &reg2,
 291                                   "target voltage", "mV");
 292
 293        wm831x_battey_apply_config(wm831x, fast_ilims, ARRAY_SIZE(fast_ilims),
 294                                   pdata->fast_ilim, &reg2,
 295                                   "fast charge current limit", "mA");
 296
 297        wm831x_battey_apply_config(wm831x, eoc_iterms, ARRAY_SIZE(eoc_iterms),
 298                                   pdata->eoc_iterm, &reg1,
 299                                   "end of charge current threshold", "mA");
 300
 301        wm831x_battey_apply_config(wm831x, chg_times, ARRAY_SIZE(chg_times),
 302                                   pdata->timeout, &reg2,
 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");
 742