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 | |
| 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')
| -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 ff1f42398a2..92c16e1677b 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; |
