root/drivers/power/supply/act8945a_charger.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. act8945a_get_charger_state
  2. act8945a_get_charge_type
  3. act8945a_get_battery_health
  4. act8945a_get_capacity_level
  5. act8945a_get_current_max
  6. act8945a_charger_get_property
  7. act8945a_enable_interrupt
  8. act8945a_set_supply_type
  9. act8945a_work
  10. act8945a_status_changed
  11. act8945a_charger_config
  12. act8945a_charger_probe
  13. act8945a_charger_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Power supply driver for the Active-semi ACT8945A PMIC
   4  *
   5  * Copyright (C) 2015 Atmel Corporation
   6  *
   7  * Author: Wenyou Yang <wenyou.yang@atmel.com>
   8  */
   9 #include <linux/interrupt.h>
  10 #include <linux/module.h>
  11 #include <linux/of.h>
  12 #include <linux/of_irq.h>
  13 #include <linux/platform_device.h>
  14 #include <linux/power_supply.h>
  15 #include <linux/regmap.h>
  16 #include <linux/gpio/consumer.h>
  17 
  18 static const char *act8945a_charger_model = "ACT8945A";
  19 static const char *act8945a_charger_manufacturer = "Active-semi";
  20 
  21 /**
  22  * ACT8945A Charger Register Map
  23  */
  24 
  25 /* 0x70: Reserved */
  26 #define ACT8945A_APCH_CFG               0x71
  27 #define ACT8945A_APCH_STATUS            0x78
  28 #define ACT8945A_APCH_CTRL              0x79
  29 #define ACT8945A_APCH_STATE             0x7A
  30 
  31 /* ACT8945A_APCH_CFG */
  32 #define APCH_CFG_OVPSET                 (0x3 << 0)
  33 #define APCH_CFG_OVPSET_6V6             (0x0 << 0)
  34 #define APCH_CFG_OVPSET_7V              (0x1 << 0)
  35 #define APCH_CFG_OVPSET_7V5             (0x2 << 0)
  36 #define APCH_CFG_OVPSET_8V              (0x3 << 0)
  37 #define APCH_CFG_PRETIMO                (0x3 << 2)
  38 #define APCH_CFG_PRETIMO_40_MIN         (0x0 << 2)
  39 #define APCH_CFG_PRETIMO_60_MIN         (0x1 << 2)
  40 #define APCH_CFG_PRETIMO_80_MIN         (0x2 << 2)
  41 #define APCH_CFG_PRETIMO_DISABLED       (0x3 << 2)
  42 #define APCH_CFG_TOTTIMO                (0x3 << 4)
  43 #define APCH_CFG_TOTTIMO_3_HOUR         (0x0 << 4)
  44 #define APCH_CFG_TOTTIMO_4_HOUR         (0x1 << 4)
  45 #define APCH_CFG_TOTTIMO_5_HOUR         (0x2 << 4)
  46 #define APCH_CFG_TOTTIMO_DISABLED       (0x3 << 4)
  47 #define APCH_CFG_SUSCHG                 (0x1 << 7)
  48 
  49 #define APCH_STATUS_CHGDAT              BIT(0)
  50 #define APCH_STATUS_INDAT               BIT(1)
  51 #define APCH_STATUS_TEMPDAT             BIT(2)
  52 #define APCH_STATUS_TIMRDAT             BIT(3)
  53 #define APCH_STATUS_CHGSTAT             BIT(4)
  54 #define APCH_STATUS_INSTAT              BIT(5)
  55 #define APCH_STATUS_TEMPSTAT            BIT(6)
  56 #define APCH_STATUS_TIMRSTAT            BIT(7)
  57 
  58 #define APCH_CTRL_CHGEOCOUT             BIT(0)
  59 #define APCH_CTRL_INDIS                 BIT(1)
  60 #define APCH_CTRL_TEMPOUT               BIT(2)
  61 #define APCH_CTRL_TIMRPRE               BIT(3)
  62 #define APCH_CTRL_CHGEOCIN              BIT(4)
  63 #define APCH_CTRL_INCON                 BIT(5)
  64 #define APCH_CTRL_TEMPIN                BIT(6)
  65 #define APCH_CTRL_TIMRTOT               BIT(7)
  66 
  67 #define APCH_STATE_ACINSTAT             (0x1 << 1)
  68 #define APCH_STATE_CSTATE               (0x3 << 4)
  69 #define APCH_STATE_CSTATE_SHIFT         4
  70 #define APCH_STATE_CSTATE_DISABLED      0x00
  71 #define APCH_STATE_CSTATE_EOC           0x01
  72 #define APCH_STATE_CSTATE_FAST          0x02
  73 #define APCH_STATE_CSTATE_PRE           0x03
  74 
  75 struct act8945a_charger {
  76         struct power_supply *psy;
  77         struct power_supply_desc desc;
  78         struct regmap *regmap;
  79         struct work_struct work;
  80 
  81         bool init_done;
  82         struct gpio_desc *lbo_gpio;
  83         struct gpio_desc *chglev_gpio;
  84 };
  85 
  86 static int act8945a_get_charger_state(struct regmap *regmap, int *val)
  87 {
  88         int ret;
  89         unsigned int status, state;
  90 
  91         ret = regmap_read(regmap, ACT8945A_APCH_STATUS, &status);
  92         if (ret < 0)
  93                 return ret;
  94 
  95         ret = regmap_read(regmap, ACT8945A_APCH_STATE, &state);
  96         if (ret < 0)
  97                 return ret;
  98 
  99         state &= APCH_STATE_CSTATE;
 100         state >>= APCH_STATE_CSTATE_SHIFT;
 101 
 102         switch (state) {
 103         case APCH_STATE_CSTATE_PRE:
 104         case APCH_STATE_CSTATE_FAST:
 105                 *val = POWER_SUPPLY_STATUS_CHARGING;
 106                 break;
 107         case APCH_STATE_CSTATE_EOC:
 108                 if (status & APCH_STATUS_CHGDAT)
 109                         *val = POWER_SUPPLY_STATUS_FULL;
 110                 else
 111                         *val = POWER_SUPPLY_STATUS_CHARGING;
 112                 break;
 113         case APCH_STATE_CSTATE_DISABLED:
 114         default:
 115                 if (!(status & APCH_STATUS_INDAT))
 116                         *val = POWER_SUPPLY_STATUS_DISCHARGING;
 117                 else
 118                         *val = POWER_SUPPLY_STATUS_NOT_CHARGING;
 119                 break;
 120         }
 121 
 122         return 0;
 123 }
 124 
 125 static int act8945a_get_charge_type(struct regmap *regmap, int *val)
 126 {
 127         int ret;
 128         unsigned int status, state;
 129 
 130         ret = regmap_read(regmap, ACT8945A_APCH_STATUS, &status);
 131         if (ret < 0)
 132                 return ret;
 133 
 134         ret = regmap_read(regmap, ACT8945A_APCH_STATE, &state);
 135         if (ret < 0)
 136                 return ret;
 137 
 138         state &= APCH_STATE_CSTATE;
 139         state >>= APCH_STATE_CSTATE_SHIFT;
 140 
 141         switch (state) {
 142         case APCH_STATE_CSTATE_PRE:
 143                 *val = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
 144                 break;
 145         case APCH_STATE_CSTATE_FAST:
 146                 *val = POWER_SUPPLY_CHARGE_TYPE_FAST;
 147                 break;
 148         case APCH_STATE_CSTATE_EOC:
 149                 *val = POWER_SUPPLY_CHARGE_TYPE_NONE;
 150                 break;
 151         case APCH_STATE_CSTATE_DISABLED:
 152         default:
 153                 if (!(status & APCH_STATUS_INDAT))
 154                         *val = POWER_SUPPLY_CHARGE_TYPE_NONE;
 155                 else
 156                         *val = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
 157                 break;
 158         }
 159 
 160         return 0;
 161 }
 162 
 163 static int act8945a_get_battery_health(struct regmap *regmap, int *val)
 164 {
 165         int ret;
 166         unsigned int status, state, config;
 167 
 168         ret = regmap_read(regmap, ACT8945A_APCH_STATUS, &status);
 169         if (ret < 0)
 170                 return ret;
 171 
 172         ret = regmap_read(regmap, ACT8945A_APCH_CFG, &config);
 173         if (ret < 0)
 174                 return ret;
 175 
 176         ret = regmap_read(regmap, ACT8945A_APCH_STATE, &state);
 177         if (ret < 0)
 178                 return ret;
 179 
 180         state &= APCH_STATE_CSTATE;
 181         state >>= APCH_STATE_CSTATE_SHIFT;
 182 
 183         switch (state) {
 184         case APCH_STATE_CSTATE_DISABLED:
 185                 if (config & APCH_CFG_SUSCHG) {
 186                         *val = POWER_SUPPLY_HEALTH_UNKNOWN;
 187                 } else if (status & APCH_STATUS_INDAT) {
 188                         if (!(status & APCH_STATUS_TEMPDAT))
 189                                 *val = POWER_SUPPLY_HEALTH_OVERHEAT;
 190                         else if (status & APCH_STATUS_TIMRDAT)
 191                                 *val = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE;
 192                         else
 193                                 *val = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
 194                 } else {
 195                         *val = POWER_SUPPLY_HEALTH_GOOD;
 196                 }
 197                 break;
 198         case APCH_STATE_CSTATE_PRE:
 199         case APCH_STATE_CSTATE_FAST:
 200         case APCH_STATE_CSTATE_EOC:
 201         default:
 202                 *val = POWER_SUPPLY_HEALTH_GOOD;
 203                 break;
 204         }
 205 
 206         return 0;
 207 }
 208 
 209 static int act8945a_get_capacity_level(struct act8945a_charger *charger,
 210                                        struct regmap *regmap, int *val)
 211 {
 212         int ret;
 213         unsigned int status, state, config;
 214         int lbo_level = gpiod_get_value(charger->lbo_gpio);
 215 
 216         ret = regmap_read(regmap, ACT8945A_APCH_STATUS, &status);
 217         if (ret < 0)
 218                 return ret;
 219 
 220         ret = regmap_read(regmap, ACT8945A_APCH_CFG, &config);
 221         if (ret < 0)
 222                 return ret;
 223 
 224         ret = regmap_read(regmap, ACT8945A_APCH_STATE, &state);
 225         if (ret < 0)
 226                 return ret;
 227 
 228         state &= APCH_STATE_CSTATE;
 229         state >>= APCH_STATE_CSTATE_SHIFT;
 230 
 231         switch (state) {
 232         case APCH_STATE_CSTATE_PRE:
 233                 *val = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
 234                 break;
 235         case APCH_STATE_CSTATE_FAST:
 236                 if (lbo_level)
 237                         *val = POWER_SUPPLY_CAPACITY_LEVEL_HIGH;
 238                 else
 239                         *val = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
 240                 break;
 241         case APCH_STATE_CSTATE_EOC:
 242                 if (status & APCH_STATUS_CHGDAT)
 243                         *val = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
 244                 else
 245                         *val = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
 246                 break;
 247         case APCH_STATE_CSTATE_DISABLED:
 248         default:
 249                 if (config & APCH_CFG_SUSCHG) {
 250                         *val = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
 251                 } else {
 252                         *val = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
 253                         if (!(status & APCH_STATUS_INDAT)) {
 254                                 if (!lbo_level)
 255                                         *val = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
 256                         }
 257                 }
 258                 break;
 259         }
 260 
 261         return 0;
 262 }
 263 
 264 #define MAX_CURRENT_USB_HIGH    450000
 265 #define MAX_CURRENT_USB_LOW     90000
 266 #define MAX_CURRENT_USB_PRE     45000
 267 /*
 268  * Riset(K) = 2336 * (1V/Ichg(mA)) - 0.205
 269  * Riset = 2.43K
 270  */
 271 #define MAX_CURRENT_AC_HIGH             886527
 272 #define MAX_CURRENT_AC_LOW              117305
 273 #define MAX_CURRENT_AC_HIGH_PRE         88653
 274 #define MAX_CURRENT_AC_LOW_PRE          11731
 275 
 276 static int act8945a_get_current_max(struct act8945a_charger *charger,
 277                                     struct regmap *regmap, int *val)
 278 {
 279         int ret;
 280         unsigned int status, state;
 281         unsigned int acin_state;
 282         int chgin_level = gpiod_get_value(charger->chglev_gpio);
 283 
 284         ret = regmap_read(regmap, ACT8945A_APCH_STATUS, &status);
 285         if (ret < 0)
 286                 return ret;
 287 
 288         ret = regmap_read(regmap, ACT8945A_APCH_STATE, &state);
 289         if (ret < 0)
 290                 return ret;
 291 
 292         acin_state = (state & APCH_STATE_ACINSTAT) >> 1;
 293 
 294         state &= APCH_STATE_CSTATE;
 295         state >>= APCH_STATE_CSTATE_SHIFT;
 296 
 297         switch (state) {
 298         case APCH_STATE_CSTATE_PRE:
 299                 if (acin_state) {
 300                         if (chgin_level)
 301                                 *val = MAX_CURRENT_AC_HIGH_PRE;
 302                         else
 303                                 *val = MAX_CURRENT_AC_LOW_PRE;
 304                 } else {
 305                         *val = MAX_CURRENT_USB_PRE;
 306                 }
 307                 break;
 308         case APCH_STATE_CSTATE_FAST:
 309                 if (acin_state) {
 310                         if (chgin_level)
 311                                 *val = MAX_CURRENT_AC_HIGH;
 312                         else
 313                                 *val = MAX_CURRENT_AC_LOW;
 314                 } else {
 315                         if (chgin_level)
 316                                 *val = MAX_CURRENT_USB_HIGH;
 317                         else
 318                                 *val = MAX_CURRENT_USB_LOW;
 319                 }
 320                 break;
 321         case APCH_STATE_CSTATE_EOC:
 322         case APCH_STATE_CSTATE_DISABLED:
 323         default:
 324                 *val = 0;
 325                 break;
 326         }
 327 
 328         return 0;
 329 }
 330 
 331 static enum power_supply_property act8945a_charger_props[] = {
 332         POWER_SUPPLY_PROP_STATUS,
 333         POWER_SUPPLY_PROP_CHARGE_TYPE,
 334         POWER_SUPPLY_PROP_TECHNOLOGY,
 335         POWER_SUPPLY_PROP_HEALTH,
 336         POWER_SUPPLY_PROP_CAPACITY_LEVEL,
 337         POWER_SUPPLY_PROP_CURRENT_MAX,
 338         POWER_SUPPLY_PROP_MODEL_NAME,
 339         POWER_SUPPLY_PROP_MANUFACTURER
 340 };
 341 
 342 static int act8945a_charger_get_property(struct power_supply *psy,
 343                                          enum power_supply_property prop,
 344                                          union power_supply_propval *val)
 345 {
 346         struct act8945a_charger *charger = power_supply_get_drvdata(psy);
 347         struct regmap *regmap = charger->regmap;
 348         int ret = 0;
 349 
 350         switch (prop) {
 351         case POWER_SUPPLY_PROP_STATUS:
 352                 ret = act8945a_get_charger_state(regmap, &val->intval);
 353                 break;
 354         case POWER_SUPPLY_PROP_CHARGE_TYPE:
 355                 ret = act8945a_get_charge_type(regmap, &val->intval);
 356                 break;
 357         case POWER_SUPPLY_PROP_TECHNOLOGY:
 358                 val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
 359                 break;
 360         case POWER_SUPPLY_PROP_HEALTH:
 361                 ret = act8945a_get_battery_health(regmap, &val->intval);
 362                 break;
 363         case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
 364                 ret = act8945a_get_capacity_level(charger,
 365                                                   regmap, &val->intval);
 366                 break;
 367         case POWER_SUPPLY_PROP_CURRENT_MAX:
 368                 ret = act8945a_get_current_max(charger,
 369                                                regmap, &val->intval);
 370                 break;
 371         case POWER_SUPPLY_PROP_MODEL_NAME:
 372                 val->strval = act8945a_charger_model;
 373                 break;
 374         case POWER_SUPPLY_PROP_MANUFACTURER:
 375                 val->strval = act8945a_charger_manufacturer;
 376                 break;
 377         default:
 378                 return -EINVAL;
 379         }
 380 
 381         return ret;
 382 }
 383 
 384 static int act8945a_enable_interrupt(struct act8945a_charger *charger)
 385 {
 386         struct regmap *regmap = charger->regmap;
 387         unsigned char ctrl;
 388         int ret;
 389 
 390         ctrl = APCH_CTRL_CHGEOCOUT | APCH_CTRL_CHGEOCIN |
 391                APCH_CTRL_INDIS | APCH_CTRL_INCON |
 392                APCH_CTRL_TEMPOUT | APCH_CTRL_TEMPIN |
 393                APCH_CTRL_TIMRPRE | APCH_CTRL_TIMRTOT;
 394         ret = regmap_write(regmap, ACT8945A_APCH_CTRL, ctrl);
 395         if (ret)
 396                 return ret;
 397 
 398         ctrl = APCH_STATUS_CHGSTAT | APCH_STATUS_INSTAT |
 399                APCH_STATUS_TEMPSTAT | APCH_STATUS_TIMRSTAT;
 400         ret = regmap_write(regmap, ACT8945A_APCH_STATUS, ctrl);
 401         if (ret)
 402                 return ret;
 403 
 404         return 0;
 405 }
 406 
 407 static unsigned int act8945a_set_supply_type(struct act8945a_charger *charger,
 408                                              unsigned int *type)
 409 {
 410         unsigned int status, state;
 411         int ret;
 412 
 413         ret = regmap_read(charger->regmap, ACT8945A_APCH_STATUS, &status);
 414         if (ret < 0)
 415                 return ret;
 416 
 417         ret = regmap_read(charger->regmap, ACT8945A_APCH_STATE, &state);
 418         if (ret < 0)
 419                 return ret;
 420 
 421         if (status & APCH_STATUS_INDAT) {
 422                 if (state & APCH_STATE_ACINSTAT)
 423                         *type = POWER_SUPPLY_TYPE_MAINS;
 424                 else
 425                         *type = POWER_SUPPLY_TYPE_USB;
 426         } else {
 427                 *type = POWER_SUPPLY_TYPE_BATTERY;
 428         }
 429 
 430         return 0;
 431 }
 432 
 433 static void act8945a_work(struct work_struct *work)
 434 {
 435         struct act8945a_charger *charger =
 436                         container_of(work, struct act8945a_charger, work);
 437 
 438         act8945a_set_supply_type(charger, &charger->desc.type);
 439 
 440         power_supply_changed(charger->psy);
 441 }
 442 
 443 static irqreturn_t act8945a_status_changed(int irq, void *dev_id)
 444 {
 445         struct act8945a_charger *charger = dev_id;
 446 
 447         if (charger->init_done)
 448                 schedule_work(&charger->work);
 449 
 450         return IRQ_HANDLED;
 451 }
 452 
 453 #define DEFAULT_TOTAL_TIME_OUT          3
 454 #define DEFAULT_PRE_TIME_OUT            40
 455 #define DEFAULT_INPUT_OVP_THRESHOLD     6600
 456 
 457 static int act8945a_charger_config(struct device *dev,
 458                                    struct act8945a_charger *charger)
 459 {
 460         struct device_node *np = dev->of_node;
 461         struct regmap *regmap = charger->regmap;
 462 
 463         u32 total_time_out;
 464         u32 pre_time_out;
 465         u32 input_voltage_threshold;
 466         int err, ret;
 467 
 468         unsigned int tmp;
 469         unsigned int value = 0;
 470 
 471         if (!np) {
 472                 dev_err(dev, "no charger of node\n");
 473                 return -EINVAL;
 474         }
 475 
 476         ret = regmap_read(regmap, ACT8945A_APCH_CFG, &tmp);
 477         if (ret)
 478                 return ret;
 479 
 480         if (tmp & APCH_CFG_SUSCHG) {
 481                 value |= APCH_CFG_SUSCHG;
 482                 dev_info(dev, "have been suspended\n");
 483         }
 484 
 485         charger->lbo_gpio = devm_gpiod_get_optional(dev, "active-semi,lbo",
 486                                                     GPIOD_IN);
 487         if (IS_ERR(charger->lbo_gpio)) {
 488                 err = PTR_ERR(charger->lbo_gpio);
 489                 dev_err(dev, "unable to claim gpio \"lbo\": %d\n", err);
 490                 return err;
 491         }
 492 
 493         ret = devm_request_irq(dev, gpiod_to_irq(charger->lbo_gpio),
 494                                act8945a_status_changed,
 495                                (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING),
 496                                "act8945a_lbo_detect", charger);
 497         if (ret)
 498                 dev_info(dev, "failed to request gpio \"lbo\" IRQ\n");
 499 
 500         charger->chglev_gpio = devm_gpiod_get_optional(dev,
 501                                                        "active-semi,chglev",
 502                                                        GPIOD_IN);
 503         if (IS_ERR(charger->chglev_gpio)) {
 504                 err = PTR_ERR(charger->chglev_gpio);
 505                 dev_err(dev, "unable to claim gpio \"chglev\": %d\n", err);
 506                 return err;
 507         }
 508 
 509         if (of_property_read_u32(np,
 510                                  "active-semi,input-voltage-threshold-microvolt",
 511                                  &input_voltage_threshold))
 512                 input_voltage_threshold = DEFAULT_INPUT_OVP_THRESHOLD;
 513 
 514         if (of_property_read_u32(np,
 515                                  "active-semi,precondition-timeout",
 516                                  &pre_time_out))
 517                 pre_time_out = DEFAULT_PRE_TIME_OUT;
 518 
 519         if (of_property_read_u32(np, "active-semi,total-timeout",
 520                                  &total_time_out))
 521                 total_time_out = DEFAULT_TOTAL_TIME_OUT;
 522 
 523         switch (input_voltage_threshold) {
 524         case 8000:
 525                 value |= APCH_CFG_OVPSET_8V;
 526                 break;
 527         case 7500:
 528                 value |= APCH_CFG_OVPSET_7V5;
 529                 break;
 530         case 7000:
 531                 value |= APCH_CFG_OVPSET_7V;
 532                 break;
 533         case 6600:
 534         default:
 535                 value |= APCH_CFG_OVPSET_6V6;
 536                 break;
 537         }
 538 
 539         switch (pre_time_out) {
 540         case 60:
 541                 value |= APCH_CFG_PRETIMO_60_MIN;
 542                 break;
 543         case 80:
 544                 value |= APCH_CFG_PRETIMO_80_MIN;
 545                 break;
 546         case 0:
 547                 value |= APCH_CFG_PRETIMO_DISABLED;
 548                 break;
 549         case 40:
 550         default:
 551                 value |= APCH_CFG_PRETIMO_40_MIN;
 552                 break;
 553         }
 554 
 555         switch (total_time_out) {
 556         case 4:
 557                 value |= APCH_CFG_TOTTIMO_4_HOUR;
 558                 break;
 559         case 5:
 560                 value |= APCH_CFG_TOTTIMO_5_HOUR;
 561                 break;
 562         case 0:
 563                 value |= APCH_CFG_TOTTIMO_DISABLED;
 564                 break;
 565         case 3:
 566         default:
 567                 value |= APCH_CFG_TOTTIMO_3_HOUR;
 568                 break;
 569         }
 570 
 571         return regmap_write(regmap, ACT8945A_APCH_CFG, value);
 572 }
 573 
 574 static int act8945a_charger_probe(struct platform_device *pdev)
 575 {
 576         struct act8945a_charger *charger;
 577         struct power_supply_config psy_cfg = {};
 578         int irq, ret;
 579 
 580         charger = devm_kzalloc(&pdev->dev, sizeof(*charger), GFP_KERNEL);
 581         if (!charger)
 582                 return -ENOMEM;
 583 
 584         charger->regmap = dev_get_regmap(pdev->dev.parent, NULL);
 585         if (!charger->regmap) {
 586                 dev_err(&pdev->dev, "Parent did not provide regmap\n");
 587                 return -EINVAL;
 588         }
 589 
 590         ret = act8945a_charger_config(&pdev->dev, charger);
 591         if (ret)
 592                 return ret;
 593 
 594         irq = of_irq_get(pdev->dev.of_node, 0);
 595         if (irq <= 0) {
 596                 dev_err(&pdev->dev, "failed to find IRQ number\n");
 597                 return irq ?: -ENXIO;
 598         }
 599 
 600         ret = devm_request_irq(&pdev->dev, irq, act8945a_status_changed,
 601                                IRQF_TRIGGER_FALLING, "act8945a_interrupt",
 602                                charger);
 603         if (ret) {
 604                 dev_err(&pdev->dev, "failed to request nIRQ pin IRQ\n");
 605                 return ret;
 606         }
 607 
 608         charger->desc.name = "act8945a-charger";
 609         charger->desc.get_property = act8945a_charger_get_property;
 610         charger->desc.properties = act8945a_charger_props;
 611         charger->desc.num_properties = ARRAY_SIZE(act8945a_charger_props);
 612 
 613         ret = act8945a_set_supply_type(charger, &charger->desc.type);
 614         if (ret)
 615                 return -EINVAL;
 616 
 617         psy_cfg.of_node = pdev->dev.of_node;
 618         psy_cfg.drv_data = charger;
 619 
 620         charger->psy = devm_power_supply_register(&pdev->dev,
 621                                                   &charger->desc,
 622                                                   &psy_cfg);
 623         if (IS_ERR(charger->psy)) {
 624                 dev_err(&pdev->dev, "failed to register power supply\n");
 625                 return PTR_ERR(charger->psy);
 626         }
 627 
 628         platform_set_drvdata(pdev, charger);
 629 
 630         INIT_WORK(&charger->work, act8945a_work);
 631 
 632         ret = act8945a_enable_interrupt(charger);
 633         if (ret)
 634                 return -EIO;
 635 
 636         charger->init_done = true;
 637 
 638         return 0;
 639 }
 640 
 641 static int act8945a_charger_remove(struct platform_device *pdev)
 642 {
 643         struct act8945a_charger *charger = platform_get_drvdata(pdev);
 644 
 645         charger->init_done = false;
 646         cancel_work_sync(&charger->work);
 647 
 648         return 0;
 649 }
 650 
 651 static struct platform_driver act8945a_charger_driver = {
 652         .driver = {
 653                 .name = "act8945a-charger",
 654         },
 655         .probe  = act8945a_charger_probe,
 656         .remove = act8945a_charger_remove,
 657 };
 658 module_platform_driver(act8945a_charger_driver);
 659 
 660 MODULE_DESCRIPTION("Active-semi ACT8945A ActivePath charger driver");
 661 MODULE_AUTHOR("Wenyou Yang <wenyou.yang@atmel.com>");
 662 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */