static void twl4030_id_workaround_work(struct work_struct *work) { struct twl4030_usb *twl = container_of(work, struct twl4030_usb, id_workaround_work.work); enum omap_musb_vbus_id_status status; bool status_changed = false; status = twl4030_usb_linkstat(twl); spin_lock_irq(&twl->lock); if (status >= 0 && status != twl->linkstat) { twl->linkstat = status; status_changed = true; } spin_unlock_irq(&twl->lock); if (status_changed) { dev_dbg(twl->dev, "handle missing status change to %d\n", status); omap_musb_mailbox(status); } /* don't schedule during sleep - irq works right then */ if (status == OMAP_MUSB_ID_GROUND && !twl->asleep) { cancel_delayed_work(&twl->id_workaround_work); schedule_delayed_work(&twl->id_workaround_work, HZ); } }
static irqreturn_t twl4030_usb_irq(int irq, void *_twl) { struct twl4030_usb *twl = _twl; enum omap_musb_vbus_id_status status; bool status_changed = false; status = twl4030_usb_linkstat(twl); spin_lock_irq(&twl->lock); if (status >= 0 && status != twl->linkstat) { twl->linkstat = status; status_changed = true; } spin_unlock_irq(&twl->lock); if (status_changed) { /* FIXME add a set_power() method so that B-devices can * configure the charger appropriately. It's not always * correct to consume VBUS power, and how much current to * consume is a function of the USB configuration chosen * by the host. * * REVISIT usb_gadget_vbus_connect(...) as needed, ditto * its disconnect() sibling, when changing to/from the * USB_LINK_VBUS state. musb_hdrc won't care until it * starts to handle softconnect right. */ omap_musb_mailbox(status); } sysfs_notify(&twl->dev->kobj, NULL, "vbus"); return IRQ_HANDLED; }
static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) { struct twl6030_usb *twl = _twl; enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN; u8 hw_state; int ret; hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); if (hw_state & STS_USB_ID) { ret = regulator_enable(twl->usb3v3); if (ret) dev_err(twl->dev, "Failed to enable usb3v3\n"); twl->asleep = 1; twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_CLR); twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET); status = OMAP_MUSB_ID_GROUND; twl->linkstat = status; omap_musb_mailbox(status); } else { twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_CLR); twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET); } twl6030_writeb(twl, TWL_MODULE_USB, status, USB_ID_INT_LATCH_CLR); return IRQ_HANDLED; }
static irqreturn_t twl4030_usb_irq(int irq, void *_twl) { struct twl4030_usb *twl = _twl; enum omap_musb_vbus_id_status status; bool status_changed = false; status = twl4030_usb_linkstat(twl); spin_lock_irq(&twl->lock); if (status >= 0 && status != twl->linkstat) { twl->linkstat = status; status_changed = true; } spin_unlock_irq(&twl->lock); if (status_changed) { /* FIXME add a set_power() method so that B-devices can * configure the charger appropriately. It's not always * correct to consume VBUS power, and how much current to * consume is a function of the USB configuration chosen * by the host. * * REVISIT usb_gadget_vbus_connect(...) as needed, ditto * its disconnect() sibling, when changing to/from the * USB_LINK_VBUS state. musb_hdrc won't care until it * starts to handle softconnect right. */ if ((status == OMAP_MUSB_VBUS_VALID) || (status == OMAP_MUSB_ID_GROUND)) { if (twl->asleep) pm_runtime_get_sync(twl->dev); } else { if (!twl->asleep) { pm_runtime_mark_last_busy(twl->dev); pm_runtime_put_autosuspend(twl->dev); } } omap_musb_mailbox(status); } /* don't schedule during sleep - irq works right then */ if (status == OMAP_MUSB_ID_GROUND && !twl->asleep) { cancel_delayed_work(&twl->id_workaround_work); schedule_delayed_work(&twl->id_workaround_work, HZ); } if (irq) sysfs_notify(&twl->dev->kobj, NULL, "vbus"); return IRQ_HANDLED; }
static irqreturn_t twl6030_usb_irq(int irq, void *_twl) { struct twl6030_usb *twl = _twl; enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN; u8 vbus_state, hw_state; int ret; hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); vbus_state = twl6030_readb(twl, TWL_MODULE_MAIN_CHARGE, CONTROLLER_STAT1); if (!(hw_state & STS_USB_ID)) { if (vbus_state & VBUS_DET) { ret = regulator_enable(twl->usb3v3); if (ret) dev_err(twl->dev, "Failed to enable usb3v3\n"); twl->asleep = 1; status = OMAP_MUSB_VBUS_VALID; twl->linkstat = status; omap_musb_mailbox(status); } else { if (twl->linkstat != OMAP_MUSB_UNKNOWN) { status = OMAP_MUSB_VBUS_OFF; twl->linkstat = status; omap_musb_mailbox(status); if (twl->asleep) { regulator_disable(twl->usb3v3); twl->asleep = 0; } } } } sysfs_notify(&twl->dev->kobj, NULL, "vbus"); return IRQ_HANDLED; }
static int twl4030_phy_init(struct phy *phy) { struct twl4030_usb *twl = phy_get_drvdata(phy); enum omap_musb_vbus_id_status status; pm_runtime_get_sync(twl->dev); status = twl4030_usb_linkstat(twl); twl->linkstat = status; if (status == OMAP_MUSB_ID_GROUND || status == OMAP_MUSB_VBUS_VALID) omap_musb_mailbox(twl->linkstat); sysfs_notify(&twl->dev->kobj, NULL, "vbus"); pm_runtime_mark_last_busy(twl->dev); pm_runtime_put_autosuspend(twl->dev); return 0; }
static int twl4030_phy_init(struct phy *phy) { struct twl4030_usb *twl = phy_get_drvdata(phy); enum omap_musb_vbus_id_status status; /* * Start in sleep state, we'll get called through set_suspend() * callback when musb is runtime resumed and it's time to start. */ __twl4030_phy_power(twl, 0); twl->asleep = 1; status = twl4030_usb_linkstat(twl); twl->linkstat = status; if (status == OMAP_MUSB_ID_GROUND || status == OMAP_MUSB_VBUS_VALID) { omap_musb_mailbox(twl->linkstat); twl4030_phy_power_on(phy); } sysfs_notify(&twl->dev->kobj, NULL, "vbus"); return 0; }