Commit c26964ead57f0aa1dff4926aae2982b174798e7b

Authored by Mark Brown
Committed by Anton Vorontsov
1 parent a9366e61b0

wm831x: Factor out WM831x backup battery charger

The backup battery on WM831x is a separate IP block to the main PMU
and is largely unrelated to the main supply functionality. Factor it
out into a separate driver in order to reflect this and better support
future hardware versions.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Acked-by: Samuel Ortiz <sameo@linux.intel.com>
Signed-off-by: Anton Vorontsov <cbouatmailru@gmail.com>

Showing 5 changed files with 253 additions and 141 deletions Side-by-side Diff

drivers/mfd/wm831x-core.c
... ... @@ -794,6 +794,9 @@
794 794  
795 795 static struct mfd_cell wm8310_devs[] = {
796 796 {
  797 + .name = "wm831x-backup",
  798 + },
  799 + {
797 800 .name = "wm831x-buckv",
798 801 .id = 1,
799 802 .num_resources = ARRAY_SIZE(wm831x_dcdc1_resources),
... ... @@ -947,6 +950,9 @@
947 950  
948 951 static struct mfd_cell wm8311_devs[] = {
949 952 {
  953 + .name = "wm831x-backup",
  954 + },
  955 + {
950 956 .name = "wm831x-buckv",
951 957 .id = 1,
952 958 .num_resources = ARRAY_SIZE(wm831x_dcdc1_resources),
... ... @@ -1080,6 +1086,9 @@
1080 1086 };
1081 1087  
1082 1088 static struct mfd_cell wm8312_devs[] = {
  1089 + {
  1090 + .name = "wm831x-backup",
  1091 + },
1083 1092 {
1084 1093 .name = "wm831x-buckv",
1085 1094 .id = 1,
drivers/power/Kconfig
... ... @@ -29,6 +29,13 @@
29 29 Say Y here to enable support APM status emulation using
30 30 battery class devices.
31 31  
  32 +config WM831X_BACKUP
  33 + tristate "WM831X backup battery charger support"
  34 + depends on MFD_WM831X
  35 + help
  36 + Say Y here to enable support for the backup battery charger
  37 + in the Wolfson Microelectronics WM831x PMICs.
  38 +
32 39 config WM831X_POWER
33 40 tristate "WM831X PMU support"
34 41 depends on MFD_WM831X
drivers/power/Makefile
... ... @@ -16,6 +16,7 @@
16 16  
17 17 obj-$(CONFIG_PDA_POWER) += pda_power.o
18 18 obj-$(CONFIG_APM_POWER) += apm_power.o
  19 +obj-$(CONFIG_WM831X_BACKUP) += wm831x_backup.o
19 20 obj-$(CONFIG_WM831X_POWER) += wm831x_power.o
20 21 obj-$(CONFIG_WM8350_POWER) += wm8350_power.o
21 22  
drivers/power/wm831x_backup.c
  1 +/*
  2 + * Backup battery driver for Wolfson Microelectronics wm831x PMICs
  3 + *
  4 + * Copyright 2009 Wolfson Microelectronics PLC.
  5 + *
  6 + * This program is free software; you can redistribute it and/or modify
  7 + * it under the terms of the GNU General Public License version 2 as
  8 + * published by the Free Software Foundation.
  9 + */
  10 +
  11 +#include <linux/module.h>
  12 +#include <linux/err.h>
  13 +#include <linux/platform_device.h>
  14 +#include <linux/power_supply.h>
  15 +
  16 +#include <linux/mfd/wm831x/core.h>
  17 +#include <linux/mfd/wm831x/auxadc.h>
  18 +#include <linux/mfd/wm831x/pmu.h>
  19 +#include <linux/mfd/wm831x/pdata.h>
  20 +
  21 +struct wm831x_backup {
  22 + struct wm831x *wm831x;
  23 + struct power_supply backup;
  24 +};
  25 +
  26 +static int wm831x_backup_read_voltage(struct wm831x *wm831x,
  27 + enum wm831x_auxadc src,
  28 + union power_supply_propval *val)
  29 +{
  30 + int ret;
  31 +
  32 + ret = wm831x_auxadc_read_uv(wm831x, src);
  33 + if (ret >= 0)
  34 + val->intval = ret;
  35 +
  36 + return ret;
  37 +}
  38 +
  39 +/*********************************************************************
  40 + * Backup supply properties
  41 + *********************************************************************/
  42 +
  43 +static void wm831x_config_backup(struct wm831x *wm831x)
  44 +{
  45 + struct wm831x_pdata *wm831x_pdata = wm831x->dev->platform_data;
  46 + struct wm831x_backup_pdata *pdata;
  47 + int ret, reg;
  48 +
  49 + if (!wm831x_pdata || !wm831x_pdata->backup) {
  50 + dev_warn(wm831x->dev,
  51 + "No backup battery charger configuration\n");
  52 + return;
  53 + }
  54 +
  55 + pdata = wm831x_pdata->backup;
  56 +
  57 + reg = 0;
  58 +
  59 + if (pdata->charger_enable)
  60 + reg |= WM831X_BKUP_CHG_ENA | WM831X_BKUP_BATT_DET_ENA;
  61 + if (pdata->no_constant_voltage)
  62 + reg |= WM831X_BKUP_CHG_MODE;
  63 +
  64 + switch (pdata->vlim) {
  65 + case 2500:
  66 + break;
  67 + case 3100:
  68 + reg |= WM831X_BKUP_CHG_VLIM;
  69 + break;
  70 + default:
  71 + dev_err(wm831x->dev, "Invalid backup voltage limit %dmV\n",
  72 + pdata->vlim);
  73 + }
  74 +
  75 + switch (pdata->ilim) {
  76 + case 100:
  77 + break;
  78 + case 200:
  79 + reg |= 1;
  80 + break;
  81 + case 300:
  82 + reg |= 2;
  83 + break;
  84 + case 400:
  85 + reg |= 3;
  86 + break;
  87 + default:
  88 + dev_err(wm831x->dev, "Invalid backup current limit %duA\n",
  89 + pdata->ilim);
  90 + }
  91 +
  92 + ret = wm831x_reg_unlock(wm831x);
  93 + if (ret != 0) {
  94 + dev_err(wm831x->dev, "Failed to unlock registers: %d\n", ret);
  95 + return;
  96 + }
  97 +
  98 + ret = wm831x_set_bits(wm831x, WM831X_BACKUP_CHARGER_CONTROL,
  99 + WM831X_BKUP_CHG_ENA_MASK |
  100 + WM831X_BKUP_CHG_MODE_MASK |
  101 + WM831X_BKUP_BATT_DET_ENA_MASK |
  102 + WM831X_BKUP_CHG_VLIM_MASK |
  103 + WM831X_BKUP_CHG_ILIM_MASK,
  104 + reg);
  105 + if (ret != 0)
  106 + dev_err(wm831x->dev,
  107 + "Failed to set backup charger config: %d\n", ret);
  108 +
  109 + wm831x_reg_lock(wm831x);
  110 +}
  111 +
  112 +static int wm831x_backup_get_prop(struct power_supply *psy,
  113 + enum power_supply_property psp,
  114 + union power_supply_propval *val)
  115 +{
  116 + struct wm831x_backup *devdata = dev_get_drvdata(psy->dev->parent);
  117 + struct wm831x *wm831x = devdata->wm831x;
  118 + int ret = 0;
  119 +
  120 + ret = wm831x_reg_read(wm831x, WM831X_BACKUP_CHARGER_CONTROL);
  121 + if (ret < 0)
  122 + return ret;
  123 +
  124 + switch (psp) {
  125 + case POWER_SUPPLY_PROP_STATUS:
  126 + if (ret & WM831X_BKUP_CHG_STS)
  127 + val->intval = POWER_SUPPLY_STATUS_CHARGING;
  128 + else
  129 + val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
  130 + break;
  131 +
  132 + case POWER_SUPPLY_PROP_VOLTAGE_NOW:
  133 + ret = wm831x_backup_read_voltage(wm831x, WM831X_AUX_BKUP_BATT,
  134 + val);
  135 + break;
  136 +
  137 + case POWER_SUPPLY_PROP_PRESENT:
  138 + if (ret & WM831X_BKUP_CHG_STS)
  139 + val->intval = 1;
  140 + else
  141 + val->intval = 0;
  142 + break;
  143 +
  144 + default:
  145 + ret = -EINVAL;
  146 + break;
  147 + }
  148 +
  149 + return ret;
  150 +}
  151 +
  152 +static enum power_supply_property wm831x_backup_props[] = {
  153 + POWER_SUPPLY_PROP_STATUS,
  154 + POWER_SUPPLY_PROP_VOLTAGE_NOW,
  155 + POWER_SUPPLY_PROP_PRESENT,
  156 +};
  157 +
  158 +/*********************************************************************
  159 + * Initialisation
  160 + *********************************************************************/
  161 +
  162 +static __devinit int wm831x_backup_probe(struct platform_device *pdev)
  163 +{
  164 + struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
  165 + struct wm831x_backup *devdata;
  166 + struct power_supply *backup;
  167 + int ret, irq, i;
  168 +
  169 + devdata = kzalloc(sizeof(struct wm831x_backup), GFP_KERNEL);
  170 + if (devdata == NULL)
  171 + return -ENOMEM;
  172 +
  173 + devdata->wm831x = wm831x;
  174 + platform_set_drvdata(pdev, devdata);
  175 +
  176 + backup = &devdata->backup;
  177 +
  178 + /* We ignore configuration failures since we can still read
  179 + * back the status without enabling the charger (which may
  180 + * already be enabled anyway).
  181 + */
  182 + wm831x_config_backup(wm831x);
  183 +
  184 + backup->name = "wm831x-backup";
  185 + backup->type = POWER_SUPPLY_TYPE_BATTERY;
  186 + backup->properties = wm831x_backup_props;
  187 + backup->num_properties = ARRAY_SIZE(wm831x_backup_props);
  188 + backup->get_property = wm831x_backup_get_prop;
  189 + ret = power_supply_register(&pdev->dev, backup);
  190 + if (ret)
  191 + goto err_kmalloc;
  192 +
  193 + return ret;
  194 +
  195 +err_kmalloc:
  196 + kfree(devdata);
  197 + return ret;
  198 +}
  199 +
  200 +static __devexit int wm831x_backup_remove(struct platform_device *pdev)
  201 +{
  202 + struct wm831x_backup *devdata = platform_get_drvdata(pdev);
  203 +
  204 + power_supply_unregister(&devdata->backup);
  205 + kfree(devdata);
  206 +
  207 + return 0;
  208 +}
  209 +
  210 +static struct platform_driver wm831x_backup_driver = {
  211 + .probe = wm831x_backup_probe,
  212 + .remove = __devexit_p(wm831x_backup_remove),
  213 + .driver = {
  214 + .name = "wm831x-backup",
  215 + },
  216 +};
  217 +
  218 +static int __init wm831x_backup_init(void)
  219 +{
  220 + return platform_driver_register(&wm831x_backup_driver);
  221 +}
  222 +module_init(wm831x_backup_init);
  223 +
  224 +static void __exit wm831x_backup_exit(void)
  225 +{
  226 + platform_driver_unregister(&wm831x_backup_driver);
  227 +}
  228 +module_exit(wm831x_backup_exit);
  229 +
  230 +MODULE_DESCRIPTION("Backup battery charger driver for WM831x PMICs");
  231 +MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
  232 +MODULE_LICENSE("GPL");
  233 +MODULE_ALIAS("platform:wm831x-backup");
drivers/power/wm831x_power.c
... ... @@ -21,7 +21,6 @@
21 21 struct wm831x_power {
22 22 struct wm831x *wm831x;
23 23 struct power_supply wall;
24   - struct power_supply backup;
25 24 struct power_supply usb;
26 25 struct power_supply battery;
27 26 };
... ... @@ -454,125 +453,6 @@
454 453  
455 454  
456 455 /*********************************************************************
457   - * Backup supply properties
458   - *********************************************************************/
459   -
460   -static void wm831x_config_backup(struct wm831x *wm831x)
461   -{
462   - struct wm831x_pdata *wm831x_pdata = wm831x->dev->platform_data;
463   - struct wm831x_backup_pdata *pdata;
464   - int ret, reg;
465   -
466   - if (!wm831x_pdata || !wm831x_pdata->backup) {
467   - dev_warn(wm831x->dev,
468   - "No backup battery charger configuration\n");
469   - return;
470   - }
471   -
472   - pdata = wm831x_pdata->backup;
473   -
474   - reg = 0;
475   -
476   - if (pdata->charger_enable)
477   - reg |= WM831X_BKUP_CHG_ENA | WM831X_BKUP_BATT_DET_ENA;
478   - if (pdata->no_constant_voltage)
479   - reg |= WM831X_BKUP_CHG_MODE;
480   -
481   - switch (pdata->vlim) {
482   - case 2500:
483   - break;
484   - case 3100:
485   - reg |= WM831X_BKUP_CHG_VLIM;
486   - break;
487   - default:
488   - dev_err(wm831x->dev, "Invalid backup voltage limit %dmV\n",
489   - pdata->vlim);
490   - }
491   -
492   - switch (pdata->ilim) {
493   - case 100:
494   - break;
495   - case 200:
496   - reg |= 1;
497   - break;
498   - case 300:
499   - reg |= 2;
500   - break;
501   - case 400:
502   - reg |= 3;
503   - break;
504   - default:
505   - dev_err(wm831x->dev, "Invalid backup current limit %duA\n",
506   - pdata->ilim);
507   - }
508   -
509   - ret = wm831x_reg_unlock(wm831x);
510   - if (ret != 0) {
511   - dev_err(wm831x->dev, "Failed to unlock registers: %d\n", ret);
512   - return;
513   - }
514   -
515   - ret = wm831x_set_bits(wm831x, WM831X_BACKUP_CHARGER_CONTROL,
516   - WM831X_BKUP_CHG_ENA_MASK |
517   - WM831X_BKUP_CHG_MODE_MASK |
518   - WM831X_BKUP_BATT_DET_ENA_MASK |
519   - WM831X_BKUP_CHG_VLIM_MASK |
520   - WM831X_BKUP_CHG_ILIM_MASK,
521   - reg);
522   - if (ret != 0)
523   - dev_err(wm831x->dev,
524   - "Failed to set backup charger config: %d\n", ret);
525   -
526   - wm831x_reg_lock(wm831x);
527   -}
528   -
529   -static int wm831x_backup_get_prop(struct power_supply *psy,
530   - enum power_supply_property psp,
531   - union power_supply_propval *val)
532   -{
533   - struct wm831x_power *wm831x_power = dev_get_drvdata(psy->dev->parent);
534   - struct wm831x *wm831x = wm831x_power->wm831x;
535   - int ret = 0;
536   -
537   - ret = wm831x_reg_read(wm831x, WM831X_BACKUP_CHARGER_CONTROL);
538   - if (ret < 0)
539   - return ret;
540   -
541   - switch (psp) {
542   - case POWER_SUPPLY_PROP_STATUS:
543   - if (ret & WM831X_BKUP_CHG_STS)
544   - val->intval = POWER_SUPPLY_STATUS_CHARGING;
545   - else
546   - val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
547   - break;
548   -
549   - case POWER_SUPPLY_PROP_VOLTAGE_NOW:
550   - ret = wm831x_power_read_voltage(wm831x, WM831X_AUX_BKUP_BATT,
551   - val);
552   - break;
553   -
554   - case POWER_SUPPLY_PROP_PRESENT:
555   - if (ret & WM831X_BKUP_CHG_STS)
556   - val->intval = 1;
557   - else
558   - val->intval = 0;
559   - break;
560   -
561   - default:
562   - ret = -EINVAL;
563   - break;
564   - }
565   -
566   - return ret;
567   -}
568   -
569   -static enum power_supply_property wm831x_backup_props[] = {
570   - POWER_SUPPLY_PROP_STATUS,
571   - POWER_SUPPLY_PROP_VOLTAGE_NOW,
572   - POWER_SUPPLY_PROP_PRESENT,
573   -};
574   -
575   -/*********************************************************************
576 456 * Initialisation
577 457 *********************************************************************/
578 458  
... ... @@ -595,10 +475,7 @@
595 475  
596 476 dev_dbg(wm831x->dev, "Power source changed\n");
597 477  
598   - /* Just notify for everything - little harm in overnotifying.
599   - * The backup battery is not a power source while the system
600   - * is running so skip that.
601   - */
  478 + /* Just notify for everything - little harm in overnotifying. */
602 479 power_supply_changed(&wm831x_power->battery);
603 480 power_supply_changed(&wm831x_power->usb);
604 481 power_supply_changed(&wm831x_power->wall);
... ... @@ -613,7 +490,6 @@
613 490 struct power_supply *usb;
614 491 struct power_supply *battery;
615 492 struct power_supply *wall;
616   - struct power_supply *backup;
617 493 int ret, irq, i;
618 494  
619 495 power = kzalloc(sizeof(struct wm831x_power), GFP_KERNEL);
620 496  
621 497  
... ... @@ -626,13 +502,11 @@
626 502 usb = &power->usb;
627 503 battery = &power->battery;
628 504 wall = &power->wall;
629   - backup = &power->backup;
630 505  
631 506 /* We ignore configuration failures since we can still read back
632   - * the status without enabling either of the chargers.
  507 + * the status without enabling the charger.
633 508 */
634 509 wm831x_config_battery(wm831x);
635   - wm831x_config_backup(wm831x);
636 510  
637 511 wall->name = "wm831x-wall";
638 512 wall->type = POWER_SUPPLY_TYPE_MAINS;
... ... @@ -661,15 +535,6 @@
661 535 if (ret)
662 536 goto err_battery;
663 537  
664   - backup->name = "wm831x-backup";
665   - backup->type = POWER_SUPPLY_TYPE_BATTERY;
666   - backup->properties = wm831x_backup_props;
667   - backup->num_properties = ARRAY_SIZE(wm831x_backup_props);
668   - backup->get_property = wm831x_backup_get_prop;
669   - ret = power_supply_register(&pdev->dev, backup);
670   - if (ret)
671   - goto err_usb;
672   -
673 538 irq = platform_get_irq_byname(pdev, "SYSLO");
674 539 ret = wm831x_request_irq(wm831x, irq, wm831x_syslo_irq,
675 540 IRQF_TRIGGER_RISING, "SYSLO",
... ... @@ -677,7 +542,7 @@
677 542 if (ret != 0) {
678 543 dev_err(&pdev->dev, "Failed to request SYSLO IRQ %d: %d\n",
679 544 irq, ret);
680   - goto err_backup;
  545 + goto err_usb;
681 546 }
682 547  
683 548 irq = platform_get_irq_byname(pdev, "PWR SRC");
... ... @@ -716,8 +581,6 @@
716 581 err_syslo:
717 582 irq = platform_get_irq_byname(pdev, "SYSLO");
718 583 wm831x_free_irq(wm831x, irq, power);
719   -err_backup:
720   - power_supply_unregister(backup);
721 584 err_usb:
722 585 power_supply_unregister(usb);
723 586 err_battery:
... ... @@ -746,7 +609,6 @@
746 609 irq = platform_get_irq_byname(pdev, "SYSLO");
747 610 wm831x_free_irq(wm831x, irq, wm831x_power);
748 611  
749   - power_supply_unregister(&wm831x_power->backup);
750 612 power_supply_unregister(&wm831x_power->battery);
751 613 power_supply_unregister(&wm831x_power->wall);
752 614 power_supply_unregister(&wm831x_power->usb);