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>
This commit is contained in:
parent
6501f728c5
commit
d6ccc442b1
1 changed files with 19 additions and 6 deletions
|
@ -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)
|
||||||
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,
|
||||||
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)
|
||||||
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;
|
||||||
|
|
Loading…
Reference in a new issue