Commit d6ccc442 authored by Heikki Krogerus's avatar Heikki Krogerus Committed by Anton Vorontsov

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: default avatarHeikki Krogerus <heikki.krogerus@nokia.com>
Tested-by: default avatarGrazvydas Ignotas <notasas@gmail.com>
Signed-off-by: default avatarAnton Vorontsov <cbouatmailru@gmail.com>
parent 6501f728
...@@ -71,8 +71,11 @@ struct twl4030_bci { ...@@ -71,8 +71,11 @@ struct twl4030_bci {
struct power_supply usb; struct power_supply usb;
struct otg_transceiver *transceiver; struct otg_transceiver *transceiver;
struct notifier_block otg_nb; struct notifier_block otg_nb;
struct work_struct work;
int irq_chg; int irq_chg;
int irq_bci; int irq_bci;
unsigned long event;
}; };
/* /*
...@@ -258,14 +261,11 @@ static irqreturn_t twl4030_bci_interrupt(int irq, void *arg) ...@@ -258,14 +261,11 @@ static irqreturn_t twl4030_bci_interrupt(int irq, void *arg)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val, static void twl4030_bci_usb_work(struct work_struct *data)
void *priv)
{ {
struct twl4030_bci *bci = container_of(nb, struct twl4030_bci, otg_nb); struct twl4030_bci *bci = container_of(data, struct twl4030_bci, work);
dev_dbg(bci->dev, "OTG notify %lu\n", val); switch (bci->event) {
switch (val) {
case USB_EVENT_VBUS: case USB_EVENT_VBUS:
case USB_EVENT_CHARGER: case USB_EVENT_CHARGER:
twl4030_charger_enable_usb(bci, true); twl4030_charger_enable_usb(bci, true);
...@@ -274,6 +274,17 @@ static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val, ...@@ -274,6 +274,17 @@ static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val,
twl4030_charger_enable_usb(bci, false); twl4030_charger_enable_usb(bci, false);
break; break;
} }
}
static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val,
void *priv)
{
struct twl4030_bci *bci = container_of(nb, struct twl4030_bci, otg_nb);
dev_dbg(bci->dev, "OTG notify %lu\n", val);
bci->event = val;
schedule_work(&bci->work);
return NOTIFY_OK; return NOTIFY_OK;
} }
...@@ -466,6 +477,8 @@ static int __init twl4030_bci_probe(struct platform_device *pdev) ...@@ -466,6 +477,8 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
goto fail_bci_irq; goto fail_bci_irq;
} }
INIT_WORK(&bci->work, twl4030_bci_usb_work);
bci->transceiver = otg_get_transceiver(); bci->transceiver = otg_get_transceiver();
if (bci->transceiver != NULL) { if (bci->transceiver != NULL) {
bci->otg_nb.notifier_call = twl4030_bci_usb_ncb; bci->otg_nb.notifier_call = twl4030_bci_usb_ncb;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment