diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-15 11:59:33 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-15 11:59:33 -0500 |
commit | 48e902f0a3aea4b6b3a73e9d277b92024a493e6d (patch) | |
tree | 6dbb3a4c5ab4e7fc72172d8c11e7c0418b6559d1 /drivers/power | |
parent | 7f6cd5408a8ace522ca7f15893243e94ccc913e0 (diff) | |
parent | 9d233e8bb92e355fd20b14745c1d9ff402e0e685 (diff) |
Merge git://git.infradead.org/battery-2.6
* git://git.infradead.org/battery-2.6:
power_supply_sysfs: Handle -ENODATA in a special way
wm831x_backup: Remove unused variables
gta02: Set pcf50633 charger_reference_current_ma
pcf50633: Query charger status directly
pcf50633: Properly reenable charging when the supply conditions change
pcf50633: Get rid of charging restart software auto-triggering
pcf50633: introduces battery charging current control
pcf50633: Add ac power supply class to the charger
wm831x: Factor out WM831x backup battery charger
Diffstat (limited to 'drivers/power')
-rw-r--r-- | drivers/power/Kconfig | 7 | ||||
-rw-r--r-- | drivers/power/Makefile | 1 | ||||
-rw-r--r-- | drivers/power/pcf50633-charger.c | 228 | ||||
-rw-r--r-- | drivers/power/power_supply_sysfs.c | 5 | ||||
-rw-r--r-- | drivers/power/wm831x_backup.c | 233 | ||||
-rw-r--r-- | drivers/power/wm831x_power.c | 144 |
6 files changed, 401 insertions, 217 deletions
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 118674925516..d4b3d67f0548 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 356cdfd3c8b2..573597c683b4 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/pcf50633-charger.c b/drivers/power/pcf50633-charger.c index 6a84a8eb8d7a..ea3fdfaca90d 100644 --- a/drivers/power/pcf50633-charger.c +++ b/drivers/power/pcf50633-charger.c | |||
@@ -29,15 +29,12 @@ | |||
29 | struct pcf50633_mbc { | 29 | struct pcf50633_mbc { |
30 | struct pcf50633 *pcf; | 30 | struct pcf50633 *pcf; |
31 | 31 | ||
32 | int adapter_active; | ||
33 | int adapter_online; | 32 | int adapter_online; |
34 | int usb_active; | ||
35 | int usb_online; | 33 | int usb_online; |
36 | 34 | ||
37 | struct power_supply usb; | 35 | struct power_supply usb; |
38 | struct power_supply adapter; | 36 | struct power_supply adapter; |
39 | 37 | struct power_supply ac; | |
40 | struct delayed_work charging_restart_work; | ||
41 | }; | 38 | }; |
42 | 39 | ||
43 | int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma) | 40 | int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma) |
@@ -47,16 +44,21 @@ int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma) | |||
47 | u8 bits; | 44 | u8 bits; |
48 | int charging_start = 1; | 45 | int charging_start = 1; |
49 | u8 mbcs2, chgmod; | 46 | u8 mbcs2, chgmod; |
47 | unsigned int mbcc5; | ||
50 | 48 | ||
51 | if (ma >= 1000) | 49 | if (ma >= 1000) { |
52 | bits = PCF50633_MBCC7_USB_1000mA; | 50 | bits = PCF50633_MBCC7_USB_1000mA; |
53 | else if (ma >= 500) | 51 | ma = 1000; |
52 | } else if (ma >= 500) { | ||
54 | bits = PCF50633_MBCC7_USB_500mA; | 53 | bits = PCF50633_MBCC7_USB_500mA; |
55 | else if (ma >= 100) | 54 | ma = 500; |
55 | } else if (ma >= 100) { | ||
56 | bits = PCF50633_MBCC7_USB_100mA; | 56 | bits = PCF50633_MBCC7_USB_100mA; |
57 | else { | 57 | ma = 100; |
58 | } else { | ||
58 | bits = PCF50633_MBCC7_USB_SUSPEND; | 59 | bits = PCF50633_MBCC7_USB_SUSPEND; |
59 | charging_start = 0; | 60 | charging_start = 0; |
61 | ma = 0; | ||
60 | } | 62 | } |
61 | 63 | ||
62 | ret = pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC7, | 64 | ret = pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC7, |
@@ -66,21 +68,40 @@ int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma) | |||
66 | else | 68 | else |
67 | dev_info(pcf->dev, "usb curlim to %d mA\n", ma); | 69 | dev_info(pcf->dev, "usb curlim to %d mA\n", ma); |
68 | 70 | ||
69 | /* Manual charging start */ | 71 | /* |
70 | mbcs2 = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2); | 72 | * We limit the charging current to be the USB current limit. |
73 | * The reason is that on pcf50633, when it enters PMU Standby mode, | ||
74 | * which it does when the device goes "off", the USB current limit | ||
75 | * reverts to the variant default. In at least one common case, that | ||
76 | * default is 500mA. By setting the charging current to be the same | ||
77 | * as the USB limit we set here before PMU standby, we enforce it only | ||
78 | * using the correct amount of current even when the USB current limit | ||
79 | * gets reset to the wrong thing | ||
80 | */ | ||
81 | |||
82 | if (mbc->pcf->pdata->charger_reference_current_ma) { | ||
83 | mbcc5 = (ma << 8) / mbc->pcf->pdata->charger_reference_current_ma; | ||
84 | if (mbcc5 > 255) | ||
85 | mbcc5 = 255; | ||
86 | pcf50633_reg_write(mbc->pcf, PCF50633_REG_MBCC5, mbcc5); | ||
87 | } | ||
88 | |||
89 | mbcs2 = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCS2); | ||
71 | chgmod = (mbcs2 & PCF50633_MBCS2_MBC_MASK); | 90 | chgmod = (mbcs2 & PCF50633_MBCS2_MBC_MASK); |
72 | 91 | ||
73 | /* If chgmod == BATFULL, setting chgena has no effect. | 92 | /* If chgmod == BATFULL, setting chgena has no effect. |
74 | * We need to set resume instead. | 93 | * Datasheet says we need to set resume instead but when autoresume is |
94 | * used resume doesn't work. Clear and set chgena instead. | ||
75 | */ | 95 | */ |
76 | if (chgmod != PCF50633_MBCS2_MBC_BAT_FULL) | 96 | if (chgmod != PCF50633_MBCS2_MBC_BAT_FULL) |
77 | pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC1, | 97 | pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC1, |
78 | PCF50633_MBCC1_CHGENA, PCF50633_MBCC1_CHGENA); | 98 | PCF50633_MBCC1_CHGENA, PCF50633_MBCC1_CHGENA); |
79 | else | 99 | else { |
100 | pcf50633_reg_clear_bits(pcf, PCF50633_REG_MBCC1, | ||
101 | PCF50633_MBCC1_CHGENA); | ||
80 | pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC1, | 102 | pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC1, |
81 | PCF50633_MBCC1_RESUME, PCF50633_MBCC1_RESUME); | 103 | PCF50633_MBCC1_CHGENA, PCF50633_MBCC1_CHGENA); |
82 | 104 | } | |
83 | mbc->usb_active = charging_start; | ||
84 | 105 | ||
85 | power_supply_changed(&mbc->usb); | 106 | power_supply_changed(&mbc->usb); |
86 | 107 | ||
@@ -92,20 +113,44 @@ int pcf50633_mbc_get_status(struct pcf50633 *pcf) | |||
92 | { | 113 | { |
93 | struct pcf50633_mbc *mbc = platform_get_drvdata(pcf->mbc_pdev); | 114 | struct pcf50633_mbc *mbc = platform_get_drvdata(pcf->mbc_pdev); |
94 | int status = 0; | 115 | int status = 0; |
116 | u8 chgmod; | ||
117 | |||
118 | if (!mbc) | ||
119 | return 0; | ||
120 | |||
121 | chgmod = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCS2) | ||
122 | & PCF50633_MBCS2_MBC_MASK; | ||
95 | 123 | ||
96 | if (mbc->usb_online) | 124 | if (mbc->usb_online) |
97 | status |= PCF50633_MBC_USB_ONLINE; | 125 | status |= PCF50633_MBC_USB_ONLINE; |
98 | if (mbc->usb_active) | 126 | if (chgmod == PCF50633_MBCS2_MBC_USB_PRE || |
127 | chgmod == PCF50633_MBCS2_MBC_USB_PRE_WAIT || | ||
128 | chgmod == PCF50633_MBCS2_MBC_USB_FAST || | ||
129 | chgmod == PCF50633_MBCS2_MBC_USB_FAST_WAIT) | ||
99 | status |= PCF50633_MBC_USB_ACTIVE; | 130 | status |= PCF50633_MBC_USB_ACTIVE; |
100 | if (mbc->adapter_online) | 131 | if (mbc->adapter_online) |
101 | status |= PCF50633_MBC_ADAPTER_ONLINE; | 132 | status |= PCF50633_MBC_ADAPTER_ONLINE; |
102 | if (mbc->adapter_active) | 133 | if (chgmod == PCF50633_MBCS2_MBC_ADP_PRE || |
134 | chgmod == PCF50633_MBCS2_MBC_ADP_PRE_WAIT || | ||
135 | chgmod == PCF50633_MBCS2_MBC_ADP_FAST || | ||
136 | chgmod == PCF50633_MBCS2_MBC_ADP_FAST_WAIT) | ||
103 | status |= PCF50633_MBC_ADAPTER_ACTIVE; | 137 | status |= PCF50633_MBC_ADAPTER_ACTIVE; |
104 | 138 | ||
105 | return status; | 139 | return status; |
106 | } | 140 | } |
107 | EXPORT_SYMBOL_GPL(pcf50633_mbc_get_status); | 141 | EXPORT_SYMBOL_GPL(pcf50633_mbc_get_status); |
108 | 142 | ||
143 | int pcf50633_mbc_get_usb_online_status(struct pcf50633 *pcf) | ||
144 | { | ||
145 | struct pcf50633_mbc *mbc = platform_get_drvdata(pcf->mbc_pdev); | ||
146 | |||
147 | if (!mbc) | ||
148 | return 0; | ||
149 | |||
150 | return mbc->usb_online; | ||
151 | } | ||
152 | EXPORT_SYMBOL_GPL(pcf50633_mbc_get_usb_online_status); | ||
153 | |||
109 | static ssize_t | 154 | static ssize_t |
110 | show_chgmode(struct device *dev, struct device_attribute *attr, char *buf) | 155 | show_chgmode(struct device *dev, struct device_attribute *attr, char *buf) |
111 | { | 156 | { |
@@ -156,9 +201,55 @@ static ssize_t set_usblim(struct device *dev, | |||
156 | 201 | ||
157 | static DEVICE_ATTR(usb_curlim, S_IRUGO | S_IWUSR, show_usblim, set_usblim); | 202 | static DEVICE_ATTR(usb_curlim, S_IRUGO | S_IWUSR, show_usblim, set_usblim); |
158 | 203 | ||
204 | static ssize_t | ||
205 | show_chglim(struct device *dev, struct device_attribute *attr, char *buf) | ||
206 | { | ||
207 | struct pcf50633_mbc *mbc = dev_get_drvdata(dev); | ||
208 | u8 mbcc5 = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCC5); | ||
209 | unsigned int ma; | ||
210 | |||
211 | if (!mbc->pcf->pdata->charger_reference_current_ma) | ||
212 | return -ENODEV; | ||
213 | |||
214 | ma = (mbc->pcf->pdata->charger_reference_current_ma * mbcc5) >> 8; | ||
215 | |||
216 | return sprintf(buf, "%u\n", ma); | ||
217 | } | ||
218 | |||
219 | static ssize_t set_chglim(struct device *dev, | ||
220 | struct device_attribute *attr, const char *buf, size_t count) | ||
221 | { | ||
222 | struct pcf50633_mbc *mbc = dev_get_drvdata(dev); | ||
223 | unsigned long ma; | ||
224 | unsigned int mbcc5; | ||
225 | int ret; | ||
226 | |||
227 | if (!mbc->pcf->pdata->charger_reference_current_ma) | ||
228 | return -ENODEV; | ||
229 | |||
230 | ret = strict_strtoul(buf, 10, &ma); | ||
231 | if (ret) | ||
232 | return -EINVAL; | ||
233 | |||
234 | mbcc5 = (ma << 8) / mbc->pcf->pdata->charger_reference_current_ma; | ||
235 | if (mbcc5 > 255) | ||
236 | mbcc5 = 255; | ||
237 | pcf50633_reg_write(mbc->pcf, PCF50633_REG_MBCC5, mbcc5); | ||
238 | |||
239 | return count; | ||
240 | } | ||
241 | |||
242 | /* | ||
243 | * This attribute allows to change MBC charging limit on the fly | ||
244 | * independently of usb current limit. It also gets set automatically every | ||
245 | * time usb current limit is changed. | ||
246 | */ | ||
247 | static DEVICE_ATTR(chg_curlim, S_IRUGO | S_IWUSR, show_chglim, set_chglim); | ||
248 | |||
159 | static struct attribute *pcf50633_mbc_sysfs_entries[] = { | 249 | static struct attribute *pcf50633_mbc_sysfs_entries[] = { |
160 | &dev_attr_chgmode.attr, | 250 | &dev_attr_chgmode.attr, |
161 | &dev_attr_usb_curlim.attr, | 251 | &dev_attr_usb_curlim.attr, |
252 | &dev_attr_chg_curlim.attr, | ||
162 | NULL, | 253 | NULL, |
163 | }; | 254 | }; |
164 | 255 | ||
@@ -167,76 +258,26 @@ static struct attribute_group mbc_attr_group = { | |||
167 | .attrs = pcf50633_mbc_sysfs_entries, | 258 | .attrs = pcf50633_mbc_sysfs_entries, |
168 | }; | 259 | }; |
169 | 260 | ||
170 | /* MBC state machine switches into charging mode when the battery voltage | ||
171 | * falls below 96% of a battery float voltage. But the voltage drop in Li-ion | ||
172 | * batteries is marginal(1~2 %) till about 80% of its capacity - which means, | ||
173 | * after a BATFULL, charging won't be restarted until 80%. | ||
174 | * | ||
175 | * This work_struct function restarts charging at regular intervals to make | ||
176 | * sure we don't discharge too much | ||
177 | */ | ||
178 | |||
179 | static void pcf50633_mbc_charging_restart(struct work_struct *work) | ||
180 | { | ||
181 | struct pcf50633_mbc *mbc; | ||
182 | u8 mbcs2, chgmod; | ||
183 | |||
184 | mbc = container_of(work, struct pcf50633_mbc, | ||
185 | charging_restart_work.work); | ||
186 | |||
187 | mbcs2 = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCS2); | ||
188 | chgmod = (mbcs2 & PCF50633_MBCS2_MBC_MASK); | ||
189 | |||
190 | if (chgmod != PCF50633_MBCS2_MBC_BAT_FULL) | ||
191 | return; | ||
192 | |||
193 | /* Restart charging */ | ||
194 | pcf50633_reg_set_bit_mask(mbc->pcf, PCF50633_REG_MBCC1, | ||
195 | PCF50633_MBCC1_RESUME, PCF50633_MBCC1_RESUME); | ||
196 | mbc->usb_active = 1; | ||
197 | power_supply_changed(&mbc->usb); | ||
198 | |||
199 | dev_info(mbc->pcf->dev, "Charging restarted\n"); | ||
200 | } | ||
201 | |||
202 | static void | 261 | static void |
203 | pcf50633_mbc_irq_handler(int irq, void *data) | 262 | pcf50633_mbc_irq_handler(int irq, void *data) |
204 | { | 263 | { |
205 | struct pcf50633_mbc *mbc = data; | 264 | struct pcf50633_mbc *mbc = data; |
206 | int chg_restart_interval = | ||
207 | mbc->pcf->pdata->charging_restart_interval; | ||
208 | 265 | ||
209 | /* USB */ | 266 | /* USB */ |
210 | if (irq == PCF50633_IRQ_USBINS) { | 267 | if (irq == PCF50633_IRQ_USBINS) { |
211 | mbc->usb_online = 1; | 268 | mbc->usb_online = 1; |
212 | } else if (irq == PCF50633_IRQ_USBREM) { | 269 | } else if (irq == PCF50633_IRQ_USBREM) { |
213 | mbc->usb_online = 0; | 270 | mbc->usb_online = 0; |
214 | mbc->usb_active = 0; | ||
215 | pcf50633_mbc_usb_curlim_set(mbc->pcf, 0); | 271 | pcf50633_mbc_usb_curlim_set(mbc->pcf, 0); |
216 | cancel_delayed_work_sync(&mbc->charging_restart_work); | ||
217 | } | 272 | } |
218 | 273 | ||
219 | /* Adapter */ | 274 | /* Adapter */ |
220 | if (irq == PCF50633_IRQ_ADPINS) { | 275 | if (irq == PCF50633_IRQ_ADPINS) |
221 | mbc->adapter_online = 1; | 276 | mbc->adapter_online = 1; |
222 | mbc->adapter_active = 1; | 277 | else if (irq == PCF50633_IRQ_ADPREM) |
223 | } else if (irq == PCF50633_IRQ_ADPREM) { | ||
224 | mbc->adapter_online = 0; | 278 | mbc->adapter_online = 0; |
225 | mbc->adapter_active = 0; | ||
226 | } | ||
227 | |||
228 | if (irq == PCF50633_IRQ_BATFULL) { | ||
229 | mbc->usb_active = 0; | ||
230 | mbc->adapter_active = 0; | ||
231 | |||
232 | if (chg_restart_interval > 0) | ||
233 | schedule_delayed_work(&mbc->charging_restart_work, | ||
234 | chg_restart_interval); | ||
235 | } else if (irq == PCF50633_IRQ_USBLIMON) | ||
236 | mbc->usb_active = 0; | ||
237 | else if (irq == PCF50633_IRQ_USBLIMOFF) | ||
238 | mbc->usb_active = 1; | ||
239 | 279 | ||
280 | power_supply_changed(&mbc->ac); | ||
240 | power_supply_changed(&mbc->usb); | 281 | power_supply_changed(&mbc->usb); |
241 | power_supply_changed(&mbc->adapter); | 282 | power_supply_changed(&mbc->adapter); |
242 | 283 | ||
@@ -269,10 +310,34 @@ static int usb_get_property(struct power_supply *psy, | |||
269 | { | 310 | { |
270 | struct pcf50633_mbc *mbc = container_of(psy, struct pcf50633_mbc, usb); | 311 | struct pcf50633_mbc *mbc = container_of(psy, struct pcf50633_mbc, usb); |
271 | int ret = 0; | 312 | int ret = 0; |
313 | u8 usblim = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCC7) & | ||
314 | PCF50633_MBCC7_USB_MASK; | ||
272 | 315 | ||
273 | switch (psp) { | 316 | switch (psp) { |
274 | case POWER_SUPPLY_PROP_ONLINE: | 317 | case POWER_SUPPLY_PROP_ONLINE: |
275 | val->intval = mbc->usb_online; | 318 | val->intval = mbc->usb_online && |
319 | (usblim <= PCF50633_MBCC7_USB_500mA); | ||
320 | break; | ||
321 | default: | ||
322 | ret = -EINVAL; | ||
323 | break; | ||
324 | } | ||
325 | return ret; | ||
326 | } | ||
327 | |||
328 | static int ac_get_property(struct power_supply *psy, | ||
329 | enum power_supply_property psp, | ||
330 | union power_supply_propval *val) | ||
331 | { | ||
332 | struct pcf50633_mbc *mbc = container_of(psy, struct pcf50633_mbc, ac); | ||
333 | int ret = 0; | ||
334 | u8 usblim = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCC7) & | ||
335 | PCF50633_MBCC7_USB_MASK; | ||
336 | |||
337 | switch (psp) { | ||
338 | case POWER_SUPPLY_PROP_ONLINE: | ||
339 | val->intval = mbc->usb_online && | ||
340 | (usblim == PCF50633_MBCC7_USB_1000mA); | ||
276 | break; | 341 | break; |
277 | default: | 342 | default: |
278 | ret = -EINVAL; | 343 | ret = -EINVAL; |
@@ -336,6 +401,14 @@ static int __devinit pcf50633_mbc_probe(struct platform_device *pdev) | |||
336 | mbc->usb.supplied_to = mbc->pcf->pdata->batteries; | 401 | mbc->usb.supplied_to = mbc->pcf->pdata->batteries; |
337 | mbc->usb.num_supplicants = mbc->pcf->pdata->num_batteries; | 402 | mbc->usb.num_supplicants = mbc->pcf->pdata->num_batteries; |
338 | 403 | ||
404 | mbc->ac.name = "ac"; | ||
405 | mbc->ac.type = POWER_SUPPLY_TYPE_MAINS; | ||
406 | mbc->ac.properties = power_props; | ||
407 | mbc->ac.num_properties = ARRAY_SIZE(power_props); | ||
408 | mbc->ac.get_property = ac_get_property; | ||
409 | mbc->ac.supplied_to = mbc->pcf->pdata->batteries; | ||
410 | mbc->ac.num_supplicants = mbc->pcf->pdata->num_batteries; | ||
411 | |||
339 | ret = power_supply_register(&pdev->dev, &mbc->adapter); | 412 | ret = power_supply_register(&pdev->dev, &mbc->adapter); |
340 | if (ret) { | 413 | if (ret) { |
341 | dev_err(mbc->pcf->dev, "failed to register adapter\n"); | 414 | dev_err(mbc->pcf->dev, "failed to register adapter\n"); |
@@ -351,8 +424,14 @@ static int __devinit pcf50633_mbc_probe(struct platform_device *pdev) | |||
351 | return ret; | 424 | return ret; |
352 | } | 425 | } |
353 | 426 | ||
354 | INIT_DELAYED_WORK(&mbc->charging_restart_work, | 427 | ret = power_supply_register(&pdev->dev, &mbc->ac); |
355 | pcf50633_mbc_charging_restart); | 428 | if (ret) { |
429 | dev_err(mbc->pcf->dev, "failed to register ac\n"); | ||
430 | power_supply_unregister(&mbc->adapter); | ||
431 | power_supply_unregister(&mbc->usb); | ||
432 | kfree(mbc); | ||
433 | return ret; | ||
434 | } | ||
356 | 435 | ||
357 | ret = sysfs_create_group(&pdev->dev.kobj, &mbc_attr_group); | 436 | ret = sysfs_create_group(&pdev->dev.kobj, &mbc_attr_group); |
358 | if (ret) | 437 | if (ret) |
@@ -378,8 +457,7 @@ static int __devexit pcf50633_mbc_remove(struct platform_device *pdev) | |||
378 | 457 | ||
379 | power_supply_unregister(&mbc->usb); | 458 | power_supply_unregister(&mbc->usb); |
380 | power_supply_unregister(&mbc->adapter); | 459 | power_supply_unregister(&mbc->adapter); |
381 | 460 | power_supply_unregister(&mbc->ac); | |
382 | cancel_delayed_work_sync(&mbc->charging_restart_work); | ||
383 | 461 | ||
384 | kfree(mbc); | 462 | kfree(mbc); |
385 | 463 | ||
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c index 08144393d64b..c790e0c77d4b 100644 --- a/drivers/power/power_supply_sysfs.c +++ b/drivers/power/power_supply_sysfs.c | |||
@@ -65,7 +65,10 @@ static ssize_t power_supply_show_property(struct device *dev, | |||
65 | ret = psy->get_property(psy, off, &value); | 65 | ret = psy->get_property(psy, off, &value); |
66 | 66 | ||
67 | if (ret < 0) { | 67 | if (ret < 0) { |
68 | if (ret != -ENODEV) | 68 | if (ret == -ENODATA) |
69 | dev_dbg(dev, "driver has no data for `%s' property\n", | ||
70 | attr->attr.name); | ||
71 | else if (ret != -ENODEV) | ||
69 | dev_err(dev, "driver failed to report `%s' property\n", | 72 | dev_err(dev, "driver failed to report `%s' property\n", |
70 | attr->attr.name); | 73 | attr->attr.name); |
71 | return ret; | 74 | return ret; |
diff --git a/drivers/power/wm831x_backup.c b/drivers/power/wm831x_backup.c new file mode 100644 index 000000000000..bf4f387a8009 --- /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; | ||
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 2a4c8b0b829c..f85e80b1b400 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); |