root/drivers/power/supply/pda_power.c

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

DEFINITIONS

This source file includes following definitions.
  1. get_irq_flags
  2. pda_power_get_property
  3. update_status
  4. update_charger
  5. supply_work_func
  6. psy_changed
  7. charger_work_func
  8. power_changed_isr
  9. polling_work_func
  10. otg_is_usb_online
  11. otg_is_ac_online
  12. otg_handle_notification
  13. pda_power_probe
  14. pda_power_remove
  15. pda_power_suspend
  16. pda_power_resume

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Common power driver for PDAs and phones with one or two external
   4  * power supplies (AC/USB) connected to main and backup batteries,
   5  * and optional builtin charger.
   6  *
   7  * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
   8  */
   9 
  10 #include <linux/module.h>
  11 #include <linux/platform_device.h>
  12 #include <linux/err.h>
  13 #include <linux/interrupt.h>
  14 #include <linux/notifier.h>
  15 #include <linux/power_supply.h>
  16 #include <linux/pda_power.h>
  17 #include <linux/regulator/consumer.h>
  18 #include <linux/timer.h>
  19 #include <linux/jiffies.h>
  20 #include <linux/usb/otg.h>
  21 
  22 static inline unsigned int get_irq_flags(struct resource *res)
  23 {
  24         return IRQF_SHARED | (res->flags & IRQF_TRIGGER_MASK);
  25 }
  26 
  27 static struct device *dev;
  28 static struct pda_power_pdata *pdata;
  29 static struct resource *ac_irq, *usb_irq;
  30 static struct delayed_work charger_work;
  31 static struct delayed_work polling_work;
  32 static struct delayed_work supply_work;
  33 static int polling;
  34 static struct power_supply *pda_psy_ac, *pda_psy_usb;
  35 
  36 #if IS_ENABLED(CONFIG_USB_PHY)
  37 static struct usb_phy *transceiver;
  38 static struct notifier_block otg_nb;
  39 #endif
  40 
  41 static struct regulator *ac_draw;
  42 
  43 enum {
  44         PDA_PSY_OFFLINE = 0,
  45         PDA_PSY_ONLINE = 1,
  46         PDA_PSY_TO_CHANGE,
  47 };
  48 static int new_ac_status = -1;
  49 static int new_usb_status = -1;
  50 static int ac_status = -1;
  51 static int usb_status = -1;
  52 
  53 static int pda_power_get_property(struct power_supply *psy,
  54                                   enum power_supply_property psp,
  55                                   union power_supply_propval *val)
  56 {
  57         switch (psp) {
  58         case POWER_SUPPLY_PROP_ONLINE:
  59                 if (psy->desc->type == POWER_SUPPLY_TYPE_MAINS)
  60                         val->intval = pdata->is_ac_online ?
  61                                       pdata->is_ac_online() : 0;
  62                 else
  63                         val->intval = pdata->is_usb_online ?
  64                                       pdata->is_usb_online() : 0;
  65                 break;
  66         default:
  67                 return -EINVAL;
  68         }
  69         return 0;
  70 }
  71 
  72 static enum power_supply_property pda_power_props[] = {
  73         POWER_SUPPLY_PROP_ONLINE,
  74 };
  75 
  76 static char *pda_power_supplied_to[] = {
  77         "main-battery",
  78         "backup-battery",
  79 };
  80 
  81 static const struct power_supply_desc pda_psy_ac_desc = {
  82         .name = "ac",
  83         .type = POWER_SUPPLY_TYPE_MAINS,
  84         .properties = pda_power_props,
  85         .num_properties = ARRAY_SIZE(pda_power_props),
  86         .get_property = pda_power_get_property,
  87 };
  88 
  89 static const struct power_supply_desc pda_psy_usb_desc = {
  90         .name = "usb",
  91         .type = POWER_SUPPLY_TYPE_USB,
  92         .properties = pda_power_props,
  93         .num_properties = ARRAY_SIZE(pda_power_props),
  94         .get_property = pda_power_get_property,
  95 };
  96 
  97 static void update_status(void)
  98 {
  99         if (pdata->is_ac_online)
 100                 new_ac_status = !!pdata->is_ac_online();
 101 
 102         if (pdata->is_usb_online)
 103                 new_usb_status = !!pdata->is_usb_online();
 104 }
 105 
 106 static void update_charger(void)
 107 {
 108         static int regulator_enabled;
 109         int max_uA = pdata->ac_max_uA;
 110 
 111         if (pdata->set_charge) {
 112                 if (new_ac_status > 0) {
 113                         dev_dbg(dev, "charger on (AC)\n");
 114                         pdata->set_charge(PDA_POWER_CHARGE_AC);
 115                 } else if (new_usb_status > 0) {
 116                         dev_dbg(dev, "charger on (USB)\n");
 117                         pdata->set_charge(PDA_POWER_CHARGE_USB);
 118                 } else {
 119                         dev_dbg(dev, "charger off\n");
 120                         pdata->set_charge(0);
 121                 }
 122         } else if (ac_draw) {
 123                 if (new_ac_status > 0) {
 124                         regulator_set_current_limit(ac_draw, max_uA, max_uA);
 125                         if (!regulator_enabled) {
 126                                 dev_dbg(dev, "charger on (AC)\n");
 127                                 WARN_ON(regulator_enable(ac_draw));
 128                                 regulator_enabled = 1;
 129                         }
 130                 } else {
 131                         if (regulator_enabled) {
 132                                 dev_dbg(dev, "charger off\n");
 133                                 WARN_ON(regulator_disable(ac_draw));
 134                                 regulator_enabled = 0;
 135                         }
 136                 }
 137         }
 138 }
 139 
 140 static void supply_work_func(struct work_struct *work)
 141 {
 142         if (ac_status == PDA_PSY_TO_CHANGE) {
 143                 ac_status = new_ac_status;
 144                 power_supply_changed(pda_psy_ac);
 145         }
 146 
 147         if (usb_status == PDA_PSY_TO_CHANGE) {
 148                 usb_status = new_usb_status;
 149                 power_supply_changed(pda_psy_usb);
 150         }
 151 }
 152 
 153 static void psy_changed(void)
 154 {
 155         update_charger();
 156 
 157         /*
 158          * Okay, charger set. Now wait a bit before notifying supplicants,
 159          * charge power should stabilize.
 160          */
 161         cancel_delayed_work(&supply_work);
 162         schedule_delayed_work(&supply_work,
 163                               msecs_to_jiffies(pdata->wait_for_charger));
 164 }
 165 
 166 static void charger_work_func(struct work_struct *work)
 167 {
 168         update_status();
 169         psy_changed();
 170 }
 171 
 172 static irqreturn_t power_changed_isr(int irq, void *power_supply)
 173 {
 174         if (power_supply == pda_psy_ac)
 175                 ac_status = PDA_PSY_TO_CHANGE;
 176         else if (power_supply == pda_psy_usb)
 177                 usb_status = PDA_PSY_TO_CHANGE;
 178         else
 179                 return IRQ_NONE;
 180 
 181         /*
 182          * Wait a bit before reading ac/usb line status and setting charger,
 183          * because ac/usb status readings may lag from irq.
 184          */
 185         cancel_delayed_work(&charger_work);
 186         schedule_delayed_work(&charger_work,
 187                               msecs_to_jiffies(pdata->wait_for_status));
 188 
 189         return IRQ_HANDLED;
 190 }
 191 
 192 static void polling_work_func(struct work_struct *work)
 193 {
 194         int changed = 0;
 195 
 196         dev_dbg(dev, "polling...\n");
 197 
 198         update_status();
 199 
 200         if (!ac_irq && new_ac_status != ac_status) {
 201                 ac_status = PDA_PSY_TO_CHANGE;
 202                 changed = 1;
 203         }
 204 
 205         if (!usb_irq && new_usb_status != usb_status) {
 206                 usb_status = PDA_PSY_TO_CHANGE;
 207                 changed = 1;
 208         }
 209 
 210         if (changed)
 211                 psy_changed();
 212 
 213         cancel_delayed_work(&polling_work);
 214         schedule_delayed_work(&polling_work,
 215                               msecs_to_jiffies(pdata->polling_interval));
 216 }
 217 
 218 #if IS_ENABLED(CONFIG_USB_PHY)
 219 static int otg_is_usb_online(void)
 220 {
 221         return (transceiver->last_event == USB_EVENT_VBUS ||
 222                 transceiver->last_event == USB_EVENT_ENUMERATED);
 223 }
 224 
 225 static int otg_is_ac_online(void)
 226 {
 227         return (transceiver->last_event == USB_EVENT_CHARGER);
 228 }
 229 
 230 static int otg_handle_notification(struct notifier_block *nb,
 231                 unsigned long event, void *unused)
 232 {
 233         switch (event) {
 234         case USB_EVENT_CHARGER:
 235                 ac_status = PDA_PSY_TO_CHANGE;
 236                 break;
 237         case USB_EVENT_VBUS:
 238         case USB_EVENT_ENUMERATED:
 239                 usb_status = PDA_PSY_TO_CHANGE;
 240                 break;
 241         case USB_EVENT_NONE:
 242                 ac_status = PDA_PSY_TO_CHANGE;
 243                 usb_status = PDA_PSY_TO_CHANGE;
 244                 break;
 245         default:
 246                 return NOTIFY_OK;
 247         }
 248 
 249         /*
 250          * Wait a bit before reading ac/usb line status and setting charger,
 251          * because ac/usb status readings may lag from irq.
 252          */
 253         cancel_delayed_work(&charger_work);
 254         schedule_delayed_work(&charger_work,
 255                               msecs_to_jiffies(pdata->wait_for_status));
 256 
 257         return NOTIFY_OK;
 258 }
 259 #endif
 260 
 261 static int pda_power_probe(struct platform_device *pdev)
 262 {
 263         struct power_supply_config psy_cfg = {};
 264         int ret = 0;
 265 
 266         dev = &pdev->dev;
 267 
 268         if (pdev->id != -1) {
 269                 dev_err(dev, "it's meaningless to register several "
 270                         "pda_powers; use id = -1\n");
 271                 ret = -EINVAL;
 272                 goto wrongid;
 273         }
 274 
 275         pdata = pdev->dev.platform_data;
 276 
 277         if (pdata->init) {
 278                 ret = pdata->init(dev);
 279                 if (ret < 0)
 280                         goto init_failed;
 281         }
 282 
 283         ac_draw = regulator_get(dev, "ac_draw");
 284         if (IS_ERR(ac_draw)) {
 285                 dev_dbg(dev, "couldn't get ac_draw regulator\n");
 286                 ac_draw = NULL;
 287         }
 288 
 289         update_status();
 290         update_charger();
 291 
 292         if (!pdata->wait_for_status)
 293                 pdata->wait_for_status = 500;
 294 
 295         if (!pdata->wait_for_charger)
 296                 pdata->wait_for_charger = 500;
 297 
 298         if (!pdata->polling_interval)
 299                 pdata->polling_interval = 2000;
 300 
 301         if (!pdata->ac_max_uA)
 302                 pdata->ac_max_uA = 500000;
 303 
 304         INIT_DELAYED_WORK(&charger_work, charger_work_func);
 305         INIT_DELAYED_WORK(&supply_work, supply_work_func);
 306 
 307         ac_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "ac");
 308         usb_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "usb");
 309 
 310         if (pdata->supplied_to) {
 311                 psy_cfg.supplied_to = pdata->supplied_to;
 312                 psy_cfg.num_supplicants = pdata->num_supplicants;
 313         } else {
 314                 psy_cfg.supplied_to = pda_power_supplied_to;
 315                 psy_cfg.num_supplicants = ARRAY_SIZE(pda_power_supplied_to);
 316         }
 317 
 318 #if IS_ENABLED(CONFIG_USB_PHY)
 319         transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
 320         if (!IS_ERR_OR_NULL(transceiver)) {
 321                 if (!pdata->is_usb_online)
 322                         pdata->is_usb_online = otg_is_usb_online;
 323                 if (!pdata->is_ac_online)
 324                         pdata->is_ac_online = otg_is_ac_online;
 325         }
 326 #endif
 327 
 328         if (pdata->is_ac_online) {
 329                 pda_psy_ac = power_supply_register(&pdev->dev,
 330                                                    &pda_psy_ac_desc, &psy_cfg);
 331                 if (IS_ERR(pda_psy_ac)) {
 332                         dev_err(dev, "failed to register %s power supply\n",
 333                                 pda_psy_ac_desc.name);
 334                         ret = PTR_ERR(pda_psy_ac);
 335                         goto ac_supply_failed;
 336                 }
 337 
 338                 if (ac_irq) {
 339                         ret = request_irq(ac_irq->start, power_changed_isr,
 340                                           get_irq_flags(ac_irq), ac_irq->name,
 341                                           pda_psy_ac);
 342                         if (ret) {
 343                                 dev_err(dev, "request ac irq failed\n");
 344                                 goto ac_irq_failed;
 345                         }
 346                 } else {
 347                         polling = 1;
 348                 }
 349         }
 350 
 351         if (pdata->is_usb_online) {
 352                 pda_psy_usb = power_supply_register(&pdev->dev,
 353                                                     &pda_psy_usb_desc,
 354                                                     &psy_cfg);
 355                 if (IS_ERR(pda_psy_usb)) {
 356                         dev_err(dev, "failed to register %s power supply\n",
 357                                 pda_psy_usb_desc.name);
 358                         ret = PTR_ERR(pda_psy_usb);
 359                         goto usb_supply_failed;
 360                 }
 361 
 362                 if (usb_irq) {
 363                         ret = request_irq(usb_irq->start, power_changed_isr,
 364                                           get_irq_flags(usb_irq),
 365                                           usb_irq->name, pda_psy_usb);
 366                         if (ret) {
 367                                 dev_err(dev, "request usb irq failed\n");
 368                                 goto usb_irq_failed;
 369                         }
 370                 } else {
 371                         polling = 1;
 372                 }
 373         }
 374 
 375 #if IS_ENABLED(CONFIG_USB_PHY)
 376         if (!IS_ERR_OR_NULL(transceiver) && pdata->use_otg_notifier) {
 377                 otg_nb.notifier_call = otg_handle_notification;
 378                 ret = usb_register_notifier(transceiver, &otg_nb);
 379                 if (ret) {
 380                         dev_err(dev, "failure to register otg notifier\n");
 381                         goto otg_reg_notifier_failed;
 382                 }
 383                 polling = 0;
 384         }
 385 #endif
 386 
 387         if (polling) {
 388                 dev_dbg(dev, "will poll for status\n");
 389                 INIT_DELAYED_WORK(&polling_work, polling_work_func);
 390                 cancel_delayed_work(&polling_work);
 391                 schedule_delayed_work(&polling_work,
 392                                       msecs_to_jiffies(pdata->polling_interval));
 393         }
 394 
 395         if (ac_irq || usb_irq)
 396                 device_init_wakeup(&pdev->dev, 1);
 397 
 398         return 0;
 399 
 400 #if IS_ENABLED(CONFIG_USB_PHY)
 401 otg_reg_notifier_failed:
 402         if (pdata->is_usb_online && usb_irq)
 403                 free_irq(usb_irq->start, pda_psy_usb);
 404 #endif
 405 usb_irq_failed:
 406         if (pdata->is_usb_online)
 407                 power_supply_unregister(pda_psy_usb);
 408 usb_supply_failed:
 409         if (pdata->is_ac_online && ac_irq)
 410                 free_irq(ac_irq->start, pda_psy_ac);
 411 #if IS_ENABLED(CONFIG_USB_PHY)
 412         if (!IS_ERR_OR_NULL(transceiver))
 413                 usb_put_phy(transceiver);
 414 #endif
 415 ac_irq_failed:
 416         if (pdata->is_ac_online)
 417                 power_supply_unregister(pda_psy_ac);
 418 ac_supply_failed:
 419         if (ac_draw) {
 420                 regulator_put(ac_draw);
 421                 ac_draw = NULL;
 422         }
 423         if (pdata->exit)
 424                 pdata->exit(dev);
 425 init_failed:
 426 wrongid:
 427         return ret;
 428 }
 429 
 430 static int pda_power_remove(struct platform_device *pdev)
 431 {
 432         if (pdata->is_usb_online && usb_irq)
 433                 free_irq(usb_irq->start, pda_psy_usb);
 434         if (pdata->is_ac_online && ac_irq)
 435                 free_irq(ac_irq->start, pda_psy_ac);
 436 
 437         if (polling)
 438                 cancel_delayed_work_sync(&polling_work);
 439         cancel_delayed_work_sync(&charger_work);
 440         cancel_delayed_work_sync(&supply_work);
 441 
 442         if (pdata->is_usb_online)
 443                 power_supply_unregister(pda_psy_usb);
 444         if (pdata->is_ac_online)
 445                 power_supply_unregister(pda_psy_ac);
 446 #if IS_ENABLED(CONFIG_USB_PHY)
 447         if (!IS_ERR_OR_NULL(transceiver))
 448                 usb_put_phy(transceiver);
 449 #endif
 450         if (ac_draw) {
 451                 regulator_put(ac_draw);
 452                 ac_draw = NULL;
 453         }
 454         if (pdata->exit)
 455                 pdata->exit(dev);
 456 
 457         return 0;
 458 }
 459 
 460 #ifdef CONFIG_PM
 461 static int ac_wakeup_enabled;
 462 static int usb_wakeup_enabled;
 463 
 464 static int pda_power_suspend(struct platform_device *pdev, pm_message_t state)
 465 {
 466         if (pdata->suspend) {
 467                 int ret = pdata->suspend(state);
 468 
 469                 if (ret)
 470                         return ret;
 471         }
 472 
 473         if (device_may_wakeup(&pdev->dev)) {
 474                 if (ac_irq)
 475                         ac_wakeup_enabled = !enable_irq_wake(ac_irq->start);
 476                 if (usb_irq)
 477                         usb_wakeup_enabled = !enable_irq_wake(usb_irq->start);
 478         }
 479 
 480         return 0;
 481 }
 482 
 483 static int pda_power_resume(struct platform_device *pdev)
 484 {
 485         if (device_may_wakeup(&pdev->dev)) {
 486                 if (usb_irq && usb_wakeup_enabled)
 487                         disable_irq_wake(usb_irq->start);
 488                 if (ac_irq && ac_wakeup_enabled)
 489                         disable_irq_wake(ac_irq->start);
 490         }
 491 
 492         if (pdata->resume)
 493                 return pdata->resume();
 494 
 495         return 0;
 496 }
 497 #else
 498 #define pda_power_suspend NULL
 499 #define pda_power_resume NULL
 500 #endif /* CONFIG_PM */
 501 
 502 static struct platform_driver pda_power_pdrv = {
 503         .driver = {
 504                 .name = "pda-power",
 505         },
 506         .probe = pda_power_probe,
 507         .remove = pda_power_remove,
 508         .suspend = pda_power_suspend,
 509         .resume = pda_power_resume,
 510 };
 511 
 512 module_platform_driver(pda_power_pdrv);
 513 
 514 MODULE_LICENSE("GPL");
 515 MODULE_AUTHOR("Anton Vorontsov <cbou@mail.ru>");
 516 MODULE_ALIAS("platform:pda-power");

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