/* * Determine is the charging port DCP (dedicated charger) or CDP (Host/HUB * chargers). * * REVISIT: The method is defined in Battery Charging Specification and is * applicable to any ULPI transceiver. Nothing isp170x specific here. */ static inline int isp1704_charger_type(struct isp1704_charger *isp) { u8 reg; u8 func_ctrl; u8 otg_ctrl; int type = POWER_SUPPLY_TYPE_USB_DCP; func_ctrl = isp1704_read(isp, ULPI_FUNC_CTRL); otg_ctrl = isp1704_read(isp, ULPI_OTG_CTRL); /* disable pulldowns */ reg = ULPI_OTG_CTRL_DM_PULLDOWN | ULPI_OTG_CTRL_DP_PULLDOWN; isp1704_write(isp, ULPI_CLR(ULPI_OTG_CTRL), reg); /* full speed */ isp1704_write(isp, ULPI_CLR(ULPI_FUNC_CTRL), ULPI_FUNC_CTRL_XCVRSEL_MASK); isp1704_write(isp, ULPI_SET(ULPI_FUNC_CTRL), ULPI_FUNC_CTRL_FULL_SPEED); /* Enable strong pull-up on DP (1.5K) and reset */ reg = ULPI_FUNC_CTRL_TERMSELECT | ULPI_FUNC_CTRL_RESET; isp1704_write(isp, ULPI_SET(ULPI_FUNC_CTRL), reg); usleep_range(1000, 2000); reg = isp1704_read(isp, ULPI_DEBUG); if ((reg & 3) != 3) type = POWER_SUPPLY_TYPE_USB_CDP; /* recover original state */ isp1704_write(isp, ULPI_FUNC_CTRL, func_ctrl); isp1704_write(isp, ULPI_OTG_CTRL, otg_ctrl); return type; }
/* * ISP1704 detects PS/2 adapters as charger. To make sure the detected charger * is actually a dedicated charger, the following steps need to be taken. */ static inline int isp1704_charger_verify(struct isp1704_charger *isp) { int ret = 0; u8 r; /* Reset the transceiver */ r = isp1704_read(isp, ULPI_FUNC_CTRL); r |= ULPI_FUNC_CTRL_RESET; isp1704_write(isp, ULPI_FUNC_CTRL, r); usleep_range(1000, 2000); /* Set normal mode */ r &= ~(ULPI_FUNC_CTRL_RESET | ULPI_FUNC_CTRL_OPMODE_MASK); isp1704_write(isp, ULPI_FUNC_CTRL, r); /* Clear the DP and DM pull-down bits */ r = ULPI_OTG_CTRL_DP_PULLDOWN | ULPI_OTG_CTRL_DM_PULLDOWN; isp1704_write(isp, ULPI_CLR(ULPI_OTG_CTRL), r); /* Enable strong pull-up on DP (1.5K) and reset */ r = ULPI_FUNC_CTRL_TERMSELECT | ULPI_FUNC_CTRL_RESET; isp1704_write(isp, ULPI_SET(ULPI_FUNC_CTRL), r); usleep_range(1000, 2000); /* Read the line state */ if (!isp1704_read(isp, ULPI_DEBUG)) { /* Disable strong pull-up on DP (1.5K) */ isp1704_write(isp, ULPI_CLR(ULPI_FUNC_CTRL), ULPI_FUNC_CTRL_TERMSELECT); return 1; } /* Is it a charger or PS/2 connection */ /* Enable weak pull-up resistor on DP */ isp1704_write(isp, ULPI_SET(ISP1704_PWR_CTRL), ISP1704_PWR_CTRL_DP_WKPU_EN); /* Disable strong pull-up on DP (1.5K) */ isp1704_write(isp, ULPI_CLR(ULPI_FUNC_CTRL), ULPI_FUNC_CTRL_TERMSELECT); /* Enable weak pull-down resistor on DM */ isp1704_write(isp, ULPI_SET(ULPI_OTG_CTRL), ULPI_OTG_CTRL_DM_PULLDOWN); /* It's a charger if the line states are clear */ if (!(isp1704_read(isp, ULPI_DEBUG))) ret = 1; /* Disable weak pull-up resistor on DP */ isp1704_write(isp, ULPI_CLR(ISP1704_PWR_CTRL), ISP1704_PWR_CTRL_DP_WKPU_EN); return ret; }
static void ci13xxx_msm_connect(void) { struct ci13xxx *udc = _udc; struct usb_phy *phy = udc->transceiver; if (phy && (phy->flags & ENABLE_DP_MANUAL_PULLUP)) { int temp; usb_phy_io_write(phy, ULPI_MISC_A_VBUSVLDEXT | ULPI_MISC_A_VBUSVLDEXTSEL, ULPI_SET(ULPI_MISC_A)); temp = readl_relaxed(USB_GENCONFIG2); temp |= GENCFG2_SESS_VLD_CTRL_EN; writel_relaxed(temp, USB_GENCONFIG2); temp = readl_relaxed(USB_USBCMD); temp |= USBCMD_SESS_VLD_CTRL; writel_relaxed(temp, USB_USBCMD); /* * Add memory barrier as it is must to complete * above USB PHY and Link register writes before * moving ahead with USB peripheral mode enumeration, * otherwise USB peripheral mode may not work. */ mb(); } }
static void omap_ehci_soft_phy_reset(struct platform_device *pdev, u8 port) { struct usb_hcd *hcd = dev_get_drvdata(&pdev->dev); unsigned long timeout = jiffies + msecs_to_jiffies(1000); unsigned reg = 0; reg = ULPI_FUNC_CTRL_RESET /* FUNCTION_CTRL_SET register */ | (ULPI_SET(ULPI_FUNC_CTRL) << EHCI_INSNREG05_ULPI_REGADD_SHIFT) /* Write */ | (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT) /* PORTn */ | ((port + 1) << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT) /* start ULPI access*/ | (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT); ehci_write(hcd->regs, EHCI_INSNREG05_ULPI, reg); /* Wait for ULPI access completion */ while ((ehci_read(hcd->regs, EHCI_INSNREG05_ULPI) & (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT))) { cpu_relax(); if (time_after(jiffies, timeout)) { dev_dbg(&pdev->dev, "phy reset operation timed out\n"); break; } } }
/** * omap_ehci_soft_phy_reset - resets the phy using the reset command * @isc: omap ehci device context * @port: port to send the reset over * * * LOCKING: * none * * RETURNS: * nothing */ static void omap_ehci_soft_phy_reset(struct omap_ehci_softc *isc, unsigned int port) { unsigned long timeout = (hz < 10) ? 1 : ((100 * hz) / 1000); uint32_t reg; reg = ULPI_FUNC_CTRL_RESET /* FUNCTION_CTRL_SET register */ | (ULPI_SET(ULPI_FUNC_CTRL) << OMAP_USBHOST_INSNREG05_ULPI_REGADD_SHIFT) /* Write */ | (2 << OMAP_USBHOST_INSNREG05_ULPI_OPSEL_SHIFT) /* PORTn */ | ((port + 1) << OMAP_USBHOST_INSNREG05_ULPI_PORTSEL_SHIFT) /* start ULPI access*/ | (1 << OMAP_USBHOST_INSNREG05_ULPI_CONTROL_SHIFT); omap_ehci_write_4(isc, OMAP_USBHOST_INSNREG05_ULPI, reg); /* Wait for ULPI access completion */ while ((omap_ehci_read_4(isc, OMAP_USBHOST_INSNREG05_ULPI) & (1 << OMAP_USBHOST_INSNREG05_ULPI_CONTROL_SHIFT))) { /* Sleep for a tick */ pause("USBPHY_RESET", 1); if (timeout-- == 0) { device_printf(isc->sc_dev, "PHY reset operation timed out\n"); break; } } }
static inline int isp1704_charger_detect(struct isp1704_charger *isp) { unsigned long timeout; u8 pwr_ctrl; int ret = 0; pwr_ctrl = isp1704_read(isp, ISP1704_PWR_CTRL); /* set SW control bit in PWR_CTRL register */ isp1704_write(isp, ISP1704_PWR_CTRL, ISP1704_PWR_CTRL_SWCTRL); /* enable manual charger detection */ isp1704_write(isp, ULPI_SET(ISP1704_PWR_CTRL), ISP1704_PWR_CTRL_SWCTRL | ISP1704_PWR_CTRL_DPVSRC_EN); usleep_range(1000, 2000); timeout = jiffies + msecs_to_jiffies(300); do { /* Check if there is a charger */ if (isp1704_read(isp, ISP1704_PWR_CTRL) & ISP1704_PWR_CTRL_VDAT_DET) { ret = isp1704_charger_verify(isp); break; } } while (!time_after(jiffies, timeout) && isp->online); /* recover original state */ isp1704_write(isp, ISP1704_PWR_CTRL, pwr_ctrl); return ret; }
static inline int isp1704_charger_detect(struct isp1704_charger *isp) { unsigned long timeout; u8 r; int ret = 0; /* set SW control bit in PWR_CTRL register */ otg_io_write(isp->otg, ISP1704_PWR_CTRL, ISP1704_PWR_CTRL_SWCTRL); /* enable manual charger detection */ r = (ISP1704_PWR_CTRL_SWCTRL | ISP1704_PWR_CTRL_DPVSRC_EN); otg_io_write(isp->otg, ULPI_SET(ISP1704_PWR_CTRL), r); usleep_range(1000, 2000); timeout = jiffies + msecs_to_jiffies(300); do { /* Check if there is a charger */ if (otg_io_read(isp->otg, ISP1704_PWR_CTRL) & ISP1704_PWR_CTRL_VDAT_DET) { ret = isp1704_charger_verify(isp); break; } } while (!time_after(jiffies, timeout)); return ret; }
void omehci_soft_phy_reset(struct omehci_softc *sc, unsigned int port) { unsigned long timeout = (hz < 10) ? 1 : ((100 * hz) / 1000); uint32_t reg; reg = ULPI_FUNC_CTRL_RESET /* FUNCTION_CTRL_SET register */ | (ULPI_SET(ULPI_FUNC_CTRL) << OMAP_USBHOST_INSNREG05_ULPI_REGADD_SHIFT) /* Write */ | (2 << OMAP_USBHOST_INSNREG05_ULPI_OPSEL_SHIFT) /* PORTn */ | ((port + 1) << OMAP_USBHOST_INSNREG05_ULPI_PORTSEL_SHIFT) /* start ULPI access*/ | (1 << OMAP_USBHOST_INSNREG05_ULPI_CONTROL_SHIFT); bus_space_write_4(sc->sc.iot, sc->sc.ioh, OMAP_USBHOST_INSNREG05_ULPI, reg); timeout += 1000000; /* Wait for ULPI access completion */ while ((bus_space_read_4(sc->sc.iot, sc->sc.ioh, OMAP_USBHOST_INSNREG05_ULPI) & (1 << OMAP_USBHOST_INSNREG05_ULPI_CONTROL_SHIFT))) { /* Sleep for a tick */ delay(10); if (timeout-- == 0) { printf("PHY reset operation timed out\n"); break; } } }
static void ci13xxx_msm_connect(void) { struct ci13xxx *udc = _udc; struct usb_phy *phy = udc->transceiver; if (phy && (phy->flags & ENABLE_DP_MANUAL_PULLUP)) { int temp; usb_phy_io_write(phy, ULPI_MISC_A_VBUSVLDEXT | ULPI_MISC_A_VBUSVLDEXTSEL, ULPI_SET(ULPI_MISC_A)); temp = readl_relaxed(USB_GENCONFIG2); temp |= GENCFG2_SESS_VLD_CTRL_EN; writel_relaxed(temp, USB_GENCONFIG2); temp = readl_relaxed(USB_USBCMD); temp |= USBCMD_SESS_VLD_CTRL; writel_relaxed(temp, USB_USBCMD); /* */ mb(); } }
static void omap_ehci_soft_phy_reset(struct ehci_hcd_omap *omap, u8 port) { unsigned long timeout = jiffies + msecs_to_jiffies(1000); unsigned reg = 0; reg = ULPI_FUNC_CTRL_RESET /* FUNCTION_CTRL_SET register */ | (ULPI_SET(ULPI_FUNC_CTRL) << EHCI_INSNREG05_ULPI_REGADD_SHIFT) /* Write */ | (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT) /* PORTn */ | ((port + 1) << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT) /* start ULPI access*/ | (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT); ehci_omap_writel(omap->ehci_base, EHCI_INSNREG05_ULPI, reg); /* Wait for ULPI access completion */ while ((ehci_omap_readl(omap->ehci_base, EHCI_INSNREG05_ULPI) & (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT))) { cpu_relax(); if (time_after(jiffies, timeout)) { dev_dbg(omap->dev, "phy reset operation timed out\n"); break; } } }
static int qcom_usb_hs_phy_set_mode(struct phy *phy, enum phy_mode mode) { struct qcom_usb_hs_phy *uphy = phy_get_drvdata(phy); u8 addr; int ret; if (!uphy->vbus_edev) { u8 val = 0; switch (mode) { case PHY_MODE_USB_OTG: case PHY_MODE_USB_HOST: val |= ULPI_INT_IDGRD; /* fall through */ case PHY_MODE_USB_DEVICE: val |= ULPI_INT_SESS_VALID; default: break; } ret = ulpi_write(uphy->ulpi, ULPI_USB_INT_EN_RISE, val); if (ret) return ret; ret = ulpi_write(uphy->ulpi, ULPI_USB_INT_EN_FALL, val); } else { switch (mode) { case PHY_MODE_USB_OTG: case PHY_MODE_USB_DEVICE: addr = ULPI_SET(ULPI_MISC_A); break; case PHY_MODE_USB_HOST: addr = ULPI_CLR(ULPI_MISC_A); break; default: return -EINVAL; } ret = ulpi_write(uphy->ulpi, ULPI_SET(ULPI_PWR_CLK_MNG_REG), ULPI_PWR_OTG_COMP_DISABLE); if (ret) return ret; ret = ulpi_write(uphy->ulpi, addr, ULPI_MISC_A_VBUSVLDEXTSEL); } return ret; }
static int msm_phy_init(struct usb_phy *phy) { struct msm_otg *motg = container_of(phy, struct msm_otg, phy); struct msm_otg_platform_data *pdata = motg->pdata; u32 val, ulpi_val = 0; /* Program USB PHY Override registers. */ ulpi_init(motg); /* * It is recommended in HPG to reset USB PHY after programming * USB PHY Override registers. */ msm_phy_reset(motg); if (pdata->otg_control == OTG_PHY_CONTROL) { val = readl(USB_OTGSC); if (pdata->mode == USB_DR_MODE_OTG) { ulpi_val = ULPI_INT_IDGRD | ULPI_INT_SESS_VALID; val |= OTGSC_IDIE | OTGSC_BSVIE; } else if (pdata->mode == USB_DR_MODE_PERIPHERAL) { ulpi_val = ULPI_INT_SESS_VALID; val |= OTGSC_BSVIE; } writel(val, USB_OTGSC); ulpi_write(phy, ulpi_val, ULPI_USB_INT_EN_RISE); ulpi_write(phy, ulpi_val, ULPI_USB_INT_EN_FALL); } if (motg->manual_pullup) { val = ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT; ulpi_write(phy, val, ULPI_SET(ULPI_MISC_A)); val = readl(USB_GENCONFIG_2); val |= GENCONFIG_2_SESS_VLD_CTRL_EN; writel(val, USB_GENCONFIG_2); val = readl(USB_USBCMD); val |= USBCMD_SESS_VLD_CTRL; writel(val, USB_USBCMD); val = ulpi_read(phy, ULPI_FUNC_CTRL); val &= ~ULPI_FUNC_CTRL_OPMODE_MASK; val |= ULPI_FUNC_CTRL_OPMODE_NORMAL; ulpi_write(phy, val, ULPI_FUNC_CTRL); } if (motg->phy_number) writel(readl(USB_PHY_CTRL2) | BIT(16), USB_PHY_CTRL2); return 0; }
static int ulpi_set_vbus(struct otg_transceiver *otg, bool on) { unsigned int flags = otg_io_read(otg, ULPI_OTG_CTRL); flags &= ~(ULPI_OTG_CTRL_DRVVBUS | ULPI_OTG_CTRL_DRVVBUS_EXT); if (on) { if (otg->flags & USB_OTG_DRV_VBUS) flags |= ULPI_OTG_CTRL_DRVVBUS; if (otg->flags & USB_OTG_DRV_VBUS_EXT) flags |= ULPI_OTG_CTRL_DRVVBUS_EXT; } return otg_io_write(otg, flags, ULPI_SET(ULPI_OTG_CTRL)); }
static int qcom_usb_hs_phy_vbus_notifier(struct notifier_block *nb, unsigned long event, void *ptr) { struct qcom_usb_hs_phy *uphy; u8 addr; uphy = container_of(nb, struct qcom_usb_hs_phy, vbus_notify); if (event) addr = ULPI_SET(ULPI_MISC_A); else addr = ULPI_CLR(ULPI_MISC_A); return ulpi_write(uphy->ulpi, addr, ULPI_MISC_A_VBUSVLDEXT); }
static int ulpi_set_flags(struct otg_transceiver *otg) { unsigned int flags = 0; if (otg->flags & USB_OTG_PULLUP_ID) flags |= ULPI_OTG_CTRL_ID_PULLUP; if (otg->flags & USB_OTG_PULLDOWN_DM) flags |= ULPI_OTG_CTRL_DM_PULLDOWN; if (otg->flags & USB_OTG_PULLDOWN_DP) flags |= ULPI_OTG_CTRL_DP_PULLDOWN; if (otg->flags & USB_OTG_EXT_VBUS_INDICATOR) flags |= ULPI_OTG_CTRL_EXTVBUSIND; return otg_io_write(otg, flags, ULPI_SET(ULPI_OTG_CTRL)); }
static inline int twl4030_usb_set_bits(struct twl4030_usb *twl, u8 reg, u8 bits) { return twl4030_usb_write(twl, ULPI_SET(reg), bits); }