aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power/twl4030_charger.c
diff options
context:
space:
mode:
authorHeikki Krogerus <heikki.krogerus@nokia.com>2011-02-25 06:56:36 -0500
committerAnton Vorontsov <cbouatmailru@gmail.com>2011-02-28 09:31:51 -0500
commitd6ccc442b12102414c1343f0adacaa8a1aaa516c (patch)
treecdfec16052084bff8161ef6d7491c36441264c78 /drivers/power/twl4030_charger.c
parent6501f728c56f831626d52b236023e556bca37f51 (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.c25
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
261static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val, 264static 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
279static 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;