static enum linkstat twl4030_usb_linkstat(struct twl4030_usb *twl) { int status; int linkstat = USB_LINK_UNKNOWN; /* STS_HW_CONDITIONS */ status = twl4030_readb(twl, TWL4030_MODULE_PM_MASTER, 0x0f); if (status < 0) dev_err(twl->dev, "USB link status err %d\n", status); else if (status & BIT(7)) linkstat = USB_LINK_VBUS; else if (status & BIT(2)) linkstat = USB_LINK_ID; else linkstat = USB_LINK_NONE; dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n", status, status, linkstat); spin_lock_irq(&twl->lock); twl->linkstat = linkstat; if (linkstat == USB_LINK_ID) { twl->otg.default_a = true; twl->otg.state = OTG_STATE_A_IDLE; } else { twl->otg.default_a = false; twl->otg.state = OTG_STATE_B_IDLE; } spin_unlock_irq(&twl->lock); return linkstat; }
//&*&*&*Simon_20110615, Interrupt handling function for GPIO-41 static irqreturn_t twl4030_OTG_irq(int irq, void *_twl) { struct twl4030_usb *twl = _twl; struct otg_transceiver x = twl->otg; int status=-1; int otg_value=-1; otg_value=gpio_get_value(41); status = twl4030_readb(twl, TWL4030_MODULE_PM_MASTER, STS_HW_CONDITIONS); printk("[OTG] %s twl4030_OTG_irq =%d status=0x%02x\n",twl->otg.label,otg_value,status); if(otg_value==1) { twl4030_otg_enable(0); //Simon //msleep(500); blocking_notifier_call_chain(&twl->otg.notifier, USB_EVENT_NONE, twl->otg.gadget); msleep(200); twl4030_phy_suspend(twl, 0); sysfs_notify(&twl->dev->kobj, NULL, "vbus"); if(wake_lock_active(&usb_lock)) { wake_unlock(&usb_lock); } } return IRQ_HANDLED; }
int twl4030_cable_type_detection(void) { int dtct = 0; enum usb_xceiv_events stat = USB_EVENT_NONE; int status; if(g_twl_usb == NULL) return stat; /* * Why sleep here instead of waiting for ACCISR1 interrupt? * * Upon cable plugging the VBUS and GND signals are the first to * contact the connector pins, leaving D+/D- floating for a while so * that the charger D+/D- short cannot be detected. This leaves us * with the only option to wait a while after VBUS RISE IRQ, praying * that cable will be fully inserted by then. */ status = twl4030_readb(g_twl_usb, TWL4030_MODULE_PM_MASTER, STS_HW_CONDITIONS); if (status < 0) dev_err(g_twl_usb->dev, "USB link status err %d\n", status); else if (status & (BIT(7) | BIT(2))) { if (status & BIT(2)) stat = USB_EVENT_ID; else { /* Read charger detection status */ dtct = twl4030_readb(g_twl_usb, TWL4030_MODULE_MAIN_CHARGE, TPS65921_USB_DTCT_CTRL); if ((dtct & TPS65921_USB_DET_STS_MASK) != TPS65921_USB_DET_STS_500MA) stat = USB_EVENT_VBUS; else stat = USB_EVENT_CHARGER; printk("[twl4030-usb]USB_DTCT_CTRL=0x%02x, status=0x%02x\n", dtct, status); } } else stat = USB_EVENT_NONE; if(!wake_lock_active(&usb_lock)) wake_lock(&usb_lock); return stat; }
static enum omap_musb_vbus_id_status twl4030_usb_linkstat(struct twl4030_usb *twl) { int status; enum omap_musb_vbus_id_status linkstat = OMAP_MUSB_UNKNOWN; twl->vbus_supplied = false; /* * For ID/VBUS sensing, see manual section 15.4.8 ... * except when using only battery backup power, two * comparators produce VBUS_PRES and ID_PRES signals, * which don't match docs elsewhere. But ... BIT(7) * and BIT(2) of STS_HW_CONDITIONS, respectively, do * seem to match up. If either is true the USB_PRES * signal is active, the OTG module is activated, and * its interrupt may be raised (may wake the system). */ status = twl4030_readb(twl, TWL_MODULE_PM_MASTER, STS_HW_CONDITIONS); if (status < 0) dev_err(twl->dev, "USB link status err %d\n", status); else if (status & (BIT(7) | BIT(2))) { if (status & BIT(7)) { if (twl4030_is_driving_vbus(twl)) status &= ~BIT(7); else twl->vbus_supplied = true; } if (status & BIT(2)) linkstat = OMAP_MUSB_ID_GROUND; else if (status & BIT(7)) linkstat = OMAP_MUSB_VBUS_VALID; else linkstat = OMAP_MUSB_VBUS_OFF; } else { if (twl->linkstat != OMAP_MUSB_UNKNOWN) linkstat = OMAP_MUSB_VBUS_OFF; } dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n", status, status, linkstat); /* REVISIT this assumes host and peripheral controllers * are registered, and that both are active... */ return linkstat; }
static enum usb_xceiv_events twl4030_usb_linkstat(struct twl4030_usb *twl) { int status; int linkstat = USB_EVENT_NONE; /* * For ID/VBUS sensing, see manual section 15.4.8 ... * except when using only battery backup power, two * comparators produce VBUS_PRES and ID_PRES signals, * which don't match docs elsewhere. But ... BIT(7) * and BIT(2) of STS_HW_CONDITIONS, respectively, do * seem to match up. If either is true the USB_PRES * signal is active, the OTG module is activated, and * its interrupt may be raised (may wake the system). */ status = twl4030_readb(twl, TWL4030_MODULE_PM_MASTER, STS_HW_CONDITIONS); if (status < 0) dev_err(twl->dev, "USB link status err %d\n", status); else if (status & (BIT(7) | BIT(2))) { if (status & BIT(2)) linkstat = USB_EVENT_ID; else linkstat = USB_EVENT_VBUS; } else linkstat = USB_EVENT_NONE; dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n", status, status, linkstat); /* REVISIT this assumes host and peripheral controllers * are registered, and that both are active... */ spin_lock_irq(&twl->lock); twl->linkstat = linkstat; if (linkstat == USB_EVENT_ID) { twl->otg.default_a = true; twl->otg.state = OTG_STATE_A_IDLE; } else { twl->otg.default_a = false; twl->otg.state = OTG_STATE_B_IDLE; } spin_unlock_irq(&twl->lock); return linkstat; }
static enum usb_phy_events twl4030_usb_linkstat(struct twl4030_usb *twl) { int status; int linkstat = USB_EVENT_NONE; struct usb_otg *otg = twl->phy.otg; twl->vbus_supplied = false; status = twl4030_readb(twl, TWL4030_MODULE_PM_MASTER, STS_HW_CONDITIONS); if (status < 0) dev_err(twl->dev, "USB link status err %d\n", status); else if (status & (BIT(7) | BIT(2))) { if (status & (BIT(7))) twl->vbus_supplied = true; if (status & BIT(2)) linkstat = USB_EVENT_ID; else linkstat = USB_EVENT_VBUS; } else linkstat = USB_EVENT_NONE; dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n", status, status, linkstat); twl->phy.last_event = linkstat; spin_lock_irq(&twl->lock); twl->linkstat = linkstat; if (linkstat == USB_EVENT_ID) { otg->default_a = true; twl->phy.state = OTG_STATE_A_IDLE; } else { otg->default_a = false; twl->phy.state = OTG_STATE_B_IDLE; } spin_unlock_irq(&twl->lock); return linkstat; }
static inline int twl4030_usb_read(struct twl4030_usb *twl, u8 address) { return twl4030_readb(twl, TWL4030_MODULE_USB, address); }
static enum usb_xceiv_events twl4030_usb_linkstat(struct twl4030_usb *twl) { int status; int linkstat = USB_EVENT_NONE; /* * For ID/VBUS sensing, see manual section 15.4.8 ... * except when using only battery backup power, two * comparators produce VBUS_PRES and ID_PRES signals, * which don't match docs elsewhere. But ... BIT(7) * and BIT(2) of STS_HW_CONDITIONS, respectively, do * seem to match up. If either is true the USB_PRES * signal is active, the OTG module is activated, and * its interrupt may be raised (may wake the system). */ status = twl4030_readb(twl, TWL4030_MODULE_PM_MASTER, STS_HW_CONDITIONS); if (status < 0) dev_err(twl->dev, "USB link status err %d\n", status); else if (status & (BIT(7) | BIT(2))) { if (status & BIT(2)) linkstat = USB_EVENT_ID; else linkstat = USB_EVENT_VBUS; } else linkstat = USB_EVENT_NONE; #ifdef CONFIG_LGE_OMAP3_EXT_PWR if( twl4030_usb_irq_occured ) { if( USB_EVENT_NONE == linkstat ) { set_external_power_detect(0); schedule_work(&set_ext_pwr_twl_usb_work); #ifdef CONFIG_USB_SUPPORT_LGE_ANDROID_AUTORUN autorun_online = 0; // autorun_remote_switch_work(); #endif } else if ( USB_EVENT_VBUS == linkstat ) { lge_usb_dp_dm_check(twl); set_external_power_detect(1); schedule_work(&set_ext_pwr_twl_usb_work); } twl4030_usb_irq_occured = 0; } #endif dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n", status, status, linkstat); /* REVISIT this assumes host and peripheral controllers * are registered, and that both are active... */ spin_lock_irq(&twl->lock); twl->linkstat = linkstat; if (linkstat == USB_EVENT_ID) { twl->otg.default_a = true; twl->otg.state = OTG_STATE_A_IDLE; } else { twl->otg.default_a = false; twl->otg.state = OTG_STATE_B_IDLE; } spin_unlock_irq(&twl->lock); return linkstat; }