diff options
author | Heikki Krogerus <heikki.krogerus@nokia.com> | 2011-02-25 06:56:36 -0500 |
---|---|---|
committer | Anton Vorontsov <cbouatmailru@gmail.com> | 2011-02-28 09:31:51 -0500 |
commit | d6ccc442b12102414c1343f0adacaa8a1aaa516c (patch) | |
tree | cdfec16052084bff8161ef6d7491c36441264c78 /drivers/power/twl4030_charger.c | |
parent | 6501f728c56f831626d52b236023e556bca37f51 (diff) |
twl4030_charger: Make the driver atomic notifier safe
This queues work from the otg notification where the
i2c operations can be safely made. Needed for atomic otg
notifiers.
Signed-off-by: Heikki Krogerus <heikki.krogerus@nokia.com>
Tested-by: Grazvydas Ignotas <notasas@gmail.com>
Signed-off-by: Anton Vorontsov <cbouatmailru@gmail.com>
Diffstat (limited to 'drivers/power/twl4030_charger.c')
-rw-r--r-- | drivers/power/twl4030_charger.c | 25 |
1 files changed, 19 insertions, 6 deletions
diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c index ff1f42398a2e..92c16e1677bd 100644 --- a/drivers/power/twl4030_charger.c +++ b/drivers/power/twl4030_charger.c | |||
@@ -71,8 +71,11 @@ struct twl4030_bci { | |||
71 | struct power_supply usb; | 71 | struct power_supply usb; |
72 | struct otg_transceiver *transceiver; | 72 | struct otg_transceiver *transceiver; |
73 | struct notifier_block otg_nb; | 73 | struct notifier_block otg_nb; |
74 | struct work_struct work; | ||
74 | int irq_chg; | 75 | int irq_chg; |
75 | int irq_bci; | 76 | int irq_bci; |
77 | |||
78 | unsigned long event; | ||
76 | }; | 79 | }; |
77 | 80 | ||
78 | /* | 81 | /* |
@@ -258,14 +261,11 @@ static irqreturn_t twl4030_bci_interrupt(int irq, void *arg) | |||
258 | return IRQ_HANDLED; | 261 | return IRQ_HANDLED; |
259 | } | 262 | } |
260 | 263 | ||
261 | static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val, | 264 | static void twl4030_bci_usb_work(struct work_struct *data) |
262 | void *priv) | ||
263 | { | 265 | { |
264 | struct twl4030_bci *bci = container_of(nb, struct twl4030_bci, otg_nb); | 266 | struct twl4030_bci *bci = container_of(data, struct twl4030_bci, work); |
265 | 267 | ||
266 | dev_dbg(bci->dev, "OTG notify %lu\n", val); | 268 | switch (bci->event) { |
267 | |||
268 | switch (val) { | ||
269 | case USB_EVENT_VBUS: | 269 | case USB_EVENT_VBUS: |
270 | case USB_EVENT_CHARGER: | 270 | case USB_EVENT_CHARGER: |
271 | twl4030_charger_enable_usb(bci, true); | 271 | twl4030_charger_enable_usb(bci, true); |
@@ -274,6 +274,17 @@ static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val, | |||
274 | twl4030_charger_enable_usb(bci, false); | 274 | twl4030_charger_enable_usb(bci, false); |
275 | break; | 275 | break; |
276 | } | 276 | } |
277 | } | ||
278 | |||
279 | static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val, | ||
280 | void *priv) | ||
281 | { | ||
282 | struct twl4030_bci *bci = container_of(nb, struct twl4030_bci, otg_nb); | ||
283 | |||
284 | dev_dbg(bci->dev, "OTG notify %lu\n", val); | ||
285 | |||
286 | bci->event = val; | ||
287 | schedule_work(&bci->work); | ||
277 | 288 | ||
278 | return NOTIFY_OK; | 289 | return NOTIFY_OK; |
279 | } | 290 | } |
@@ -466,6 +477,8 @@ static int __init twl4030_bci_probe(struct platform_device *pdev) | |||
466 | goto fail_bci_irq; | 477 | goto fail_bci_irq; |
467 | } | 478 | } |
468 | 479 | ||
480 | INIT_WORK(&bci->work, twl4030_bci_usb_work); | ||
481 | |||
469 | bci->transceiver = otg_get_transceiver(); | 482 | bci->transceiver = otg_get_transceiver(); |
470 | if (bci->transceiver != NULL) { | 483 | if (bci->transceiver != NULL) { |
471 | bci->otg_nb.notifier_call = twl4030_bci_usb_ncb; | 484 | bci->otg_nb.notifier_call = twl4030_bci_usb_ncb; |