Skip to content

Commit

Permalink
twl4030_charger: Make the driver atomic notifier safe
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Heikki Krogerus authored and Anton Vorontsov committed Feb 28, 2011
1 parent 6501f72 commit d6ccc44
Showing 1 changed file with 19 additions and 6 deletions.
25 changes: 19 additions & 6 deletions drivers/power/twl4030_charger.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,11 @@ struct twl4030_bci {
struct power_supply usb;
struct otg_transceiver *transceiver;
struct notifier_block otg_nb;
struct work_struct work;
int irq_chg;
int irq_bci;

unsigned long event;
};

/*
Expand Down Expand Up @@ -258,14 +261,11 @@ static irqreturn_t twl4030_bci_interrupt(int irq, void *arg)
return IRQ_HANDLED;
}

static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val,
void *priv)
static void twl4030_bci_usb_work(struct work_struct *data)
{
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 (val) {
switch (bci->event) {
case USB_EVENT_VBUS:
case USB_EVENT_CHARGER:
twl4030_charger_enable_usb(bci, true);
Expand All @@ -274,6 +274,17 @@ static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val,
twl4030_charger_enable_usb(bci, false);
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;
}
Expand Down Expand Up @@ -466,6 +477,8 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
goto fail_bci_irq;
}

INIT_WORK(&bci->work, twl4030_bci_usb_work);

bci->transceiver = otg_get_transceiver();
if (bci->transceiver != NULL) {
bci->otg_nb.notifier_call = twl4030_bci_usb_ncb;
Expand Down

0 comments on commit d6ccc44

Please sign in to comment.