diff options
Diffstat (limited to 'drivers/power')
-rw-r--r-- | drivers/power/Kconfig | 7 | ||||
-rw-r--r-- | drivers/power/Makefile | 1 | ||||
-rw-r--r-- | drivers/power/wm831x_backup.c | 233 | ||||
-rw-r--r-- | drivers/power/wm831x_power.c | 144 |
4 files changed, 244 insertions, 141 deletions
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index cea6cef27e8..783e9b790b0 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig | |||
@@ -29,6 +29,13 @@ config APM_POWER | |||
29 | Say Y here to enable support APM status emulation using | 29 | Say Y here to enable support APM status emulation using |
30 | battery class devices. | 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 | config WM831X_POWER | 39 | config WM831X_POWER |
33 | tristate "WM831X PMU support" | 40 | tristate "WM831X PMU support" |
34 | depends on MFD_WM831X | 41 | depends on MFD_WM831X |
diff --git a/drivers/power/Makefile b/drivers/power/Makefile index b96f29d91c2..d1406b9f02f 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile | |||
@@ -16,6 +16,7 @@ obj-$(CONFIG_POWER_SUPPLY) += power_supply.o | |||
16 | 16 | ||
17 | obj-$(CONFIG_PDA_POWER) += pda_power.o | 17 | obj-$(CONFIG_PDA_POWER) += pda_power.o |
18 | obj-$(CONFIG_APM_POWER) += apm_power.o | 18 | obj-$(CONFIG_APM_POWER) += apm_power.o |
19 | obj-$(CONFIG_WM831X_BACKUP) += wm831x_backup.o | ||
19 | obj-$(CONFIG_WM831X_POWER) += wm831x_power.o | 20 | obj-$(CONFIG_WM831X_POWER) += wm831x_power.o |
20 | obj-$(CONFIG_WM8350_POWER) += wm8350_power.o | 21 | obj-$(CONFIG_WM8350_POWER) += wm8350_power.o |
21 | 22 | ||
diff --git a/drivers/power/wm831x_backup.c b/drivers/power/wm831x_backup.c new file mode 100644 index 00000000000..f181076a408 --- /dev/null +++ b/drivers/power/wm831x_backup.c | |||
@@ -0,0 +1,233 @@ | |||
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"); | ||
diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c index 2a4c8b0b829..f85e80b1b40 100644 --- a/drivers/power/wm831x_power.c +++ b/drivers/power/wm831x_power.c | |||
@@ -21,7 +21,6 @@ | |||
21 | struct wm831x_power { | 21 | struct wm831x_power { |
22 | struct wm831x *wm831x; | 22 | struct wm831x *wm831x; |
23 | struct power_supply wall; | 23 | struct power_supply wall; |
24 | struct power_supply backup; | ||
25 | struct power_supply usb; | 24 | struct power_supply usb; |
26 | struct power_supply battery; | 25 | struct power_supply battery; |
27 | }; | 26 | }; |
@@ -454,125 +453,6 @@ static irqreturn_t wm831x_bat_irq(int irq, void *data) | |||
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 | * Initialisation | 456 | * Initialisation |
577 | *********************************************************************/ | 457 | *********************************************************************/ |
578 | 458 | ||
@@ -595,10 +475,7 @@ static irqreturn_t wm831x_pwr_src_irq(int irq, void *data) | |||
595 | 475 | ||
596 | dev_dbg(wm831x->dev, "Power source changed\n"); | 476 | dev_dbg(wm831x->dev, "Power source changed\n"); |
597 | 477 | ||
598 | /* Just notify for everything - little harm in overnotifying. | 478 | /* 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 | */ | ||
602 | power_supply_changed(&wm831x_power->battery); | 479 | power_supply_changed(&wm831x_power->battery); |
603 | power_supply_changed(&wm831x_power->usb); | 480 | power_supply_changed(&wm831x_power->usb); |
604 | power_supply_changed(&wm831x_power->wall); | 481 | power_supply_changed(&wm831x_power->wall); |
@@ -613,7 +490,6 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev) | |||
613 | struct power_supply *usb; | 490 | struct power_supply *usb; |
614 | struct power_supply *battery; | 491 | struct power_supply *battery; |
615 | struct power_supply *wall; | 492 | struct power_supply *wall; |
616 | struct power_supply *backup; | ||
617 | int ret, irq, i; | 493 | int ret, irq, i; |
618 | 494 | ||
619 | power = kzalloc(sizeof(struct wm831x_power), GFP_KERNEL); | 495 | power = kzalloc(sizeof(struct wm831x_power), GFP_KERNEL); |
@@ -626,13 +502,11 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev) | |||
626 | usb = &power->usb; | 502 | usb = &power->usb; |
627 | battery = &power->battery; | 503 | battery = &power->battery; |
628 | wall = &power->wall; | 504 | wall = &power->wall; |
629 | backup = &power->backup; | ||
630 | 505 | ||
631 | /* We ignore configuration failures since we can still read back | 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 | wm831x_config_battery(wm831x); | 509 | wm831x_config_battery(wm831x); |
635 | wm831x_config_backup(wm831x); | ||
636 | 510 | ||
637 | wall->name = "wm831x-wall"; | 511 | wall->name = "wm831x-wall"; |
638 | wall->type = POWER_SUPPLY_TYPE_MAINS; | 512 | wall->type = POWER_SUPPLY_TYPE_MAINS; |
@@ -661,15 +535,6 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev) | |||
661 | if (ret) | 535 | if (ret) |
662 | goto err_battery; | 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 | irq = platform_get_irq_byname(pdev, "SYSLO"); | 538 | irq = platform_get_irq_byname(pdev, "SYSLO"); |
674 | ret = wm831x_request_irq(wm831x, irq, wm831x_syslo_irq, | 539 | ret = wm831x_request_irq(wm831x, irq, wm831x_syslo_irq, |
675 | IRQF_TRIGGER_RISING, "SYSLO", | 540 | IRQF_TRIGGER_RISING, "SYSLO", |
@@ -677,7 +542,7 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev) | |||
677 | if (ret != 0) { | 542 | if (ret != 0) { |
678 | dev_err(&pdev->dev, "Failed to request SYSLO IRQ %d: %d\n", | 543 | dev_err(&pdev->dev, "Failed to request SYSLO IRQ %d: %d\n", |
679 | irq, ret); | 544 | irq, ret); |
680 | goto err_backup; | 545 | goto err_usb; |
681 | } | 546 | } |
682 | 547 | ||
683 | irq = platform_get_irq_byname(pdev, "PWR SRC"); | 548 | irq = platform_get_irq_byname(pdev, "PWR SRC"); |
@@ -716,8 +581,6 @@ err_bat_irq: | |||
716 | err_syslo: | 581 | err_syslo: |
717 | irq = platform_get_irq_byname(pdev, "SYSLO"); | 582 | irq = platform_get_irq_byname(pdev, "SYSLO"); |
718 | wm831x_free_irq(wm831x, irq, power); | 583 | wm831x_free_irq(wm831x, irq, power); |
719 | err_backup: | ||
720 | power_supply_unregister(backup); | ||
721 | err_usb: | 584 | err_usb: |
722 | power_supply_unregister(usb); | 585 | power_supply_unregister(usb); |
723 | err_battery: | 586 | err_battery: |
@@ -746,7 +609,6 @@ static __devexit int wm831x_power_remove(struct platform_device *pdev) | |||
746 | irq = platform_get_irq_byname(pdev, "SYSLO"); | 609 | irq = platform_get_irq_byname(pdev, "SYSLO"); |
747 | wm831x_free_irq(wm831x, irq, wm831x_power); | 610 | wm831x_free_irq(wm831x, irq, wm831x_power); |
748 | 611 | ||
749 | power_supply_unregister(&wm831x_power->backup); | ||
750 | power_supply_unregister(&wm831x_power->battery); | 612 | power_supply_unregister(&wm831x_power->battery); |
751 | power_supply_unregister(&wm831x_power->wall); | 613 | power_supply_unregister(&wm831x_power->wall); |
752 | power_supply_unregister(&wm831x_power->usb); | 614 | power_supply_unregister(&wm831x_power->usb); |