static void msm_chg_block_off(struct msm_otg *motg) { struct usb_phy *phy = &motg->phy; u32 func_ctrl, chg_det; switch (motg->pdata->phy_type) { case CI_45NM_INTEGRATED_PHY: chg_det = ulpi_read(phy, 0x34); /* Turn off charger block */ chg_det |= ~(1 << 1); ulpi_write(phy, chg_det, 0x34); break; case SNPS_28NM_INTEGRATED_PHY: /* Clear charger detecting control bits */ ulpi_write(phy, 0x3F, 0x86); /* Clear alt interrupt latch and enable bits */ ulpi_write(phy, 0x1F, 0x92); ulpi_write(phy, 0x1F, 0x95); break; default: break; } /* put the controller in normal mode */ func_ctrl = ulpi_read(phy, ULPI_FUNC_CTRL); func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK; func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NORMAL; ulpi_write(phy, func_ctrl, ULPI_FUNC_CTRL); }
static int ulpi_read_id(struct ulpi *ulpi) { int ret; /* Test the interface */ ret = ulpi_write(ulpi, ULPI_SCRATCH, 0xaa); if (ret < 0) goto err; ret = ulpi_read(ulpi, ULPI_SCRATCH); if (ret < 0) return ret; if (ret != 0xaa) goto err; ulpi->id.vendor = ulpi_read(ulpi, ULPI_VENDOR_ID_LOW); ulpi->id.vendor |= ulpi_read(ulpi, ULPI_VENDOR_ID_HIGH) << 8; ulpi->id.product = ulpi_read(ulpi, ULPI_PRODUCT_ID_LOW); ulpi->id.product |= ulpi_read(ulpi, ULPI_PRODUCT_ID_HIGH) << 8; /* Some ULPI devices don't have a vendor id so rely on OF match */ if (ulpi->id.vendor == 0) goto err; request_module("ulpi:v%04xp%04x", ulpi->id.vendor, ulpi->id.product); return 0; err: of_device_request_module(&ulpi->dev); return 0; }
static void msm_chg_block_on(struct msm_otg *motg) { struct usb_phy *phy = &motg->phy; u32 func_ctrl, chg_det; /* put the controller in non-driving mode */ func_ctrl = ulpi_read(phy, ULPI_FUNC_CTRL); func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK; func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING; ulpi_write(phy, func_ctrl, ULPI_FUNC_CTRL); switch (motg->pdata->phy_type) { case CI_45NM_INTEGRATED_PHY: chg_det = ulpi_read(phy, 0x34); /* control chg block via ULPI */ chg_det &= ~(1 << 3); ulpi_write(phy, chg_det, 0x34); /* Turn on chg detect block */ chg_det &= ~(1 << 1); ulpi_write(phy, chg_det, 0x34); udelay(20); break; case SNPS_28NM_INTEGRATED_PHY: /* Clear charger detecting control bits */ ulpi_write(phy, 0x3F, 0x86); /* Clear alt interrupt latch and enable bits */ ulpi_write(phy, 0x1F, 0x92); ulpi_write(phy, 0x1F, 0x95); udelay(100); break; default: break; } }
static void msm_otg_host_phy_tune(struct msm_otg *otg, u32 paramb, u32 paramc) { ulpi_write(&otg->phy, paramb, 0x81); ulpi_write(&otg->phy, paramc, 0x82); pr_info("ULPI 0x%x: 0x%x: 0x%x: 0x%x\n", ulpi_read(&otg->phy, 0x80), ulpi_read(&otg->phy, 0x81), ulpi_read(&otg->phy, 0x82), ulpi_read(&otg->phy, 0x83)); mdelay(100); }
static int usb_suspend_ulpi_phy(struct usb_hcd *hcd) { unsigned long timeout; int ret = 0; ulpi_read(hcd, 0x14);/* clear PHY interrupt latch register */ ulpi_write(hcd, 0x08, 0x09);/* turn off PLL on integrated phy */ ulpi_write(hcd, 0x01, 0x30);/* PHY comparators on in LPM */ timeout = jiffies + msecs_to_jiffies(500); writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC); while (!(readl(USB_PORTSC) & PORTSC_PHCD)) { if (time_after(jiffies, timeout)) { pr_err("%s: Unable to suspend phy\n", __func__); ret = -1; goto out; } msleep(1); } /* block the stp signal */ writel(readl(USB_USBCMD) | ULPI_STP_CTRL, USB_USBCMD); /* enable asynchronous interrupt */ writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL, USB_USBCMD); out: return ret; }
static void target_ulpi_init(void) { unsigned int reg; reg = ulpi_read(0x32); dprintf(INFO, " Value of ulpi read 0x32 is %08x\n", reg); ulpi_write(0x30, 0x32); reg = ulpi_read(0x32); dprintf(INFO, " Value of ulpi read 0x32 after write is %08x\n", reg); reg = ulpi_read(0x36); dprintf(INFO, " Value of ulpi read 0x36 is %08x\n", reg); ulpi_write(reg | 0x2, 0x36); reg = ulpi_read(0x36); dprintf(INFO, " Value of ulpi read 0x36 aafter write is %08x\n", reg); }
static int tusb1210_set_mode(struct phy *phy, enum phy_mode mode) { struct tusb1210 *tusb = phy_get_drvdata(phy); int ret; ret = ulpi_read(tusb->ulpi, ULPI_OTG_CTRL); if (ret < 0) return ret; switch (mode) { case PHY_MODE_USB_HOST: ret |= (ULPI_OTG_CTRL_DRVVBUS_EXT | ULPI_OTG_CTRL_ID_PULLUP | ULPI_OTG_CTRL_DP_PULLDOWN | ULPI_OTG_CTRL_DM_PULLDOWN); ulpi_write(tusb->ulpi, ULPI_OTG_CTRL, ret); ret |= ULPI_OTG_CTRL_DRVVBUS; break; case PHY_MODE_USB_DEVICE: ret &= ~(ULPI_OTG_CTRL_DRVVBUS | ULPI_OTG_CTRL_DP_PULLDOWN | ULPI_OTG_CTRL_DM_PULLDOWN); ulpi_write(tusb->ulpi, ULPI_OTG_CTRL, ret); ret &= ~ULPI_OTG_CTRL_DRVVBUS_EXT; break; default: /* nothing */ return 0; } return ulpi_write(tusb->ulpi, ULPI_OTG_CTRL, ret); }
static int msm_xusb_init_phy(struct msmusb_hcd *mhcd) { int ret = -ENODEV; struct usb_hcd *hcd = mhcd_to_hcd(mhcd); struct msm_usb_host_platform_data *pdata = mhcd->pdata; unsigned temp; switch (PHY_TYPE(pdata->phy_info)) { case USB_PHY_INTEGRATED: msm_hsusb_rpc_connect(); /* VBUS might be present. Turn off vbus */ if (pdata->vbus_power) pdata->vbus_power(pdata->phy_info, 0); msm_xusb_enable_clks(mhcd); clk_enable(mhcd->clk); if (pdata->phy_reset) ret = pdata->phy_reset(hcd->regs); else ret = msm_hsusb_phy_reset(); if (ret) break; /* Give some delay to settle phy after reset */ msleep(100); /* Disable VbusValid and SessionEnd comparators */ ulpi_write(hcd, ULPI_VBUS_VALID | ULPI_SESS_END, ULPI_INT_RISE_CLR); ulpi_write(hcd, ULPI_VBUS_VALID | ULPI_SESS_END, ULPI_INT_FALL_CLR); /* set hs driver amplitude to max * to avoid eye diagram failures */ temp = ulpi_read(hcd, ULPI_CONFIG_REG); temp |= ULPI_AMPLITUDE_MAX; ulpi_write(hcd, temp, ULPI_CONFIG_REG); /* Disable all interrupts */ writel(0, USB_USBINTR); writel(readl(USB_OTGSC) & ~OTGSC_INTR_MASK, USB_OTGSC); msm_xusb_disable_clks(mhcd); clk_disable(mhcd->clk); break; case USB_PHY_SERIAL_PMIC: msm_xusb_enable_clks(mhcd); writel(0, USB_USBINTR); ret = msm_fsusb_rpc_init(&mhcd->otg_ops); if (!ret) msm_fsusb_init_phy(); msm_xusb_disable_clks(mhcd); break; default: pr_err("%s: undefined phy type ( %X ) \n", __func__, pdata->phy_info); } return ret; }
static void ehci_msm_disable_ulpi_control(struct usb_hcd *hcd) { struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd); int val; val = ulpi_read(mehci, HSIC_DBG1); val &= ~ULPI_MANUAL_ENABLE; ulpi_write(mehci, val, HSIC_DBG1); }
static int __devexit msm_otg_remove(struct platform_device *pdev) { struct msm_otg *motg = platform_get_drvdata(pdev); struct otg_transceiver *otg = &motg->otg; int cnt = 0; if (otg->host || otg->gadget) return -EBUSY; msm_otg_debugfs_cleanup(); cancel_work_sync(&motg->sm_work); msm_otg_resume(motg); device_init_wakeup(&pdev->dev, 0); pm_runtime_disable(&pdev->dev); otg_set_transceiver(NULL); free_irq(motg->irq, motg); /* * Put PHY in low power mode. */ ulpi_read(otg, 0x14); ulpi_write(otg, 0x08, 0x09); writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC); while (cnt < PHY_SUSPEND_TIMEOUT_USEC) { if (readl(USB_PORTSC) & PORTSC_PHCD) break; udelay(1); cnt++; } if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) dev_err(otg->dev, "Unable to suspend PHY\n"); clk_disable(motg->pclk); clk_disable(motg->clk); if (motg->core_clk) clk_disable(motg->core_clk); iounmap(motg->regs); pm_runtime_set_suspended(&pdev->dev); clk_put(motg->phy_reset_clk); clk_put(motg->pclk); clk_put(motg->clk); if (motg->core_clk) clk_put(motg->core_clk); kfree(motg); return 0; }
static bool msm_chg_check_dcd(struct msm_otg *motg) { struct usb_phy *phy = &motg->phy; u32 line_state; bool ret = false; switch (motg->pdata->phy_type) { case CI_45NM_INTEGRATED_PHY: line_state = ulpi_read(phy, 0x15); ret = !(line_state & 1); break; case SNPS_28NM_INTEGRATED_PHY: line_state = ulpi_read(phy, 0x87); ret = line_state & 2; break; default: break; } return ret; }
static bool msm_chg_check_primary_det(struct msm_otg *motg) { struct usb_phy *phy = &motg->phy; u32 chg_det; bool ret = false; switch (motg->pdata->phy_type) { case CI_45NM_INTEGRATED_PHY: chg_det = ulpi_read(phy, 0x34); ret = chg_det & (1 << 4); break; case SNPS_28NM_INTEGRATED_PHY: chg_det = ulpi_read(phy, 0x87); ret = chg_det & 1; break; default: break; } return ret; }
static int msm_otg_suspend(struct msm_otg *dev) { unsigned long timeout; int vbus = 0; disable_irq(dev->irq); if (atomic_read(&dev->in_lpm)) goto out; ulpi_read(dev, 0x14);/* clear PHY interrupt latch register */ /* If there is no pmic notify support turn on phy comparators. */ if (!dev->pmic_notif_supp) ulpi_write(dev, 0x01, 0x30); ulpi_write(dev, 0x08, 0x09);/* turn off PLL on integrated phy */ timeout = jiffies + msecs_to_jiffies(500); disable_phy_clk(); while (!is_phy_clk_disabled()) { if (time_after(jiffies, timeout)) { pr_err("%s: Unable to suspend phy\n", __func__); /* Reset both phy and link */ otg_reset(dev, 1); goto out; } msleep(1); } writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD); if (dev->hs_pclk) clk_disable(dev->hs_pclk); if (dev->hs_cclk) clk_disable(dev->hs_cclk); if (device_may_wakeup(dev->otg.dev)) { enable_irq_wake(dev->irq); if (dev->vbus_on_irq) enable_irq_wake(dev->vbus_on_irq); } atomic_set(&dev->in_lpm, 1); if (!vbus && dev->pmic_notif_supp) dev->pdata->pmic_enable_ldo(0); pr_info("%s: usb in low power mode\n", __func__); out: enable_irq(dev->irq); /* TBD: as there is no bus suspend implemented as of now * it should be dummy check */ return 0; }
static void target_ulpi_init(void) { unsigned int reg; ulpi_read(0x31); dprintf(INFO, " Value of ulpi read 0x31 is %08x\n", reg); /* todo : the write back value should be calculated according to * reg &= 0xF3 but sometimes the value that is read initially * doesnt look right */ ulpi_write(0x4A, 0x31); reg = ulpi_read(0x31); dprintf(INFO, " Value of ulpi read 0x31 after write is %08x\n", reg); reg = ulpi_read(0x32); dprintf(INFO, " Value of ulpi read 0x32 is %08x\n", reg); ulpi_write(0x30, 0x32); reg = ulpi_read(0x32); dprintf(INFO, " Value of ulpi read 0x32 after write is %08x\n", reg); reg = ulpi_read(0x36); dprintf(INFO, " Value of ulpi read 0x36 is %08x\n", reg); ulpi_write(reg | 0x2, 0x36); reg = ulpi_read(0x36); dprintf(INFO, " Value of ulpi read 0x36 after write is %08x\n", reg); }
static int ulpi_register(struct device *dev, struct ulpi *ulpi) { int ret; /* Test the interface */ ret = ulpi_write(ulpi, ULPI_SCRATCH, 0xaa); if (ret < 0) return ret; ret = ulpi_read(ulpi, ULPI_SCRATCH); if (ret < 0) return ret; if (ret != 0xaa) return -ENODEV; ulpi->id.vendor = ulpi_read(ulpi, ULPI_VENDOR_ID_LOW); ulpi->id.vendor |= ulpi_read(ulpi, ULPI_VENDOR_ID_HIGH) << 8; ulpi->id.product = ulpi_read(ulpi, ULPI_PRODUCT_ID_LOW); ulpi->id.product |= ulpi_read(ulpi, ULPI_PRODUCT_ID_HIGH) << 8; ulpi->dev.parent = dev; ulpi->dev.bus = &ulpi_bus; ulpi->dev.type = &ulpi_dev_type; dev_set_name(&ulpi->dev, "%s.ulpi", dev_name(dev)); ACPI_COMPANION_SET(&ulpi->dev, ACPI_COMPANION(dev)); request_module("ulpi:v%04xp%04x", ulpi->id.vendor, ulpi->id.product); ret = device_register(&ulpi->dev); if (ret) return ret; dev_dbg(&ulpi->dev, "registered ULPI PHY: vendor %04x, product %04x\n", ulpi->id.vendor, ulpi->id.product); return 0; }
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 inline void set_driver_amplitude(struct msm_otg *dev) { unsigned res = 0; if (!dev->pdata || dev->pdata->drv_ampl == HS_DRV_AMPLITUDE_DEFAULT) return; res = ulpi_read(dev, ULPI_CONFIG_REG2); res &= ~ULPI_DRV_AMPL_MASK; if (dev->pdata->drv_ampl != HS_DRV_AMPLITUDE_ZERO_PERCENT) res |= dev->pdata->drv_ampl; ulpi_write(dev, res, ULPI_CONFIG_REG2); }
static inline void set_pre_emphasis_level(struct msm_otg *dev) { unsigned res = 0; if (!dev->pdata || dev->pdata->pemp_level == PRE_EMPHASIS_DEFAULT) return; res = ulpi_read(dev, ULPI_CONFIG_REG3); res &= ~(ULPI_PRE_EMPHASIS_MASK); if (dev->pdata->pemp_level != PRE_EMPHASIS_DISABLE) res |= dev->pdata->pemp_level; ulpi_write(dev, res, ULPI_CONFIG_REG3); }
static void msm_chg_block_on(struct msm_otg *motg) { struct usb_phy *phy = &motg->phy; u32 func_ctrl, chg_det; /* put the controller in non-driving mode */ func_ctrl = ulpi_read(phy, ULPI_FUNC_CTRL); func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK; func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING; ulpi_write(phy, func_ctrl, ULPI_FUNC_CTRL); switch (motg->pdata->phy_type) { case CI_45NM_INTEGRATED
static int msm_otg_phy_reset(struct msm_otg *motg) { u32 val; int ret; int retries; ret = msm_otg_link_clk_reset(motg, 1); if (ret) return ret; ret = msm_otg_phy_clk_reset(motg); if (ret) return ret; ret = msm_otg_link_clk_reset(motg, 0); if (ret) return ret; val = readl(USB_PORTSC) & ~PORTSC_PTS_MASK; writel(val | PORTSC_PTS_ULPI, USB_PORTSC); for (retries = 3; retries > 0; retries--) { ret = ulpi_write(&motg->otg, ULPI_FUNC_CTRL_SUSPENDM, ULPI_CLR(ULPI_FUNC_CTRL)); if (!ret) break; ret = msm_otg_phy_clk_reset(motg); if (ret) return ret; } if (!retries) return -ETIMEDOUT; /* This reset calibrates the phy, if the above write succeeded */ ret = msm_otg_phy_clk_reset(motg); if (ret) return ret; for (retries = 3; retries > 0; retries--) { ret = ulpi_read(&motg->otg, ULPI_DEBUG); if (ret != -ETIMEDOUT) break; ret = msm_otg_phy_clk_reset(motg); if (ret) return ret; } if (!retries) return -ETIMEDOUT; dev_info(motg->otg.dev, "phy_reset: success\n"); return 0; }
static inline void set_cdr_auto_reset(struct msm_otg *dev) { unsigned res = 0; if (!dev->pdata || dev->pdata->cdr_autoreset == CDR_AUTO_RESET_DEFAULT) return; res = ulpi_read(dev, ULPI_DIGOUT_CTRL); if (dev->pdata->cdr_autoreset == CDR_AUTO_RESET_ENABLE) res &= ~ULPI_CDR_AUTORESET; else res |= ULPI_CDR_AUTORESET; ulpi_write(dev, res, ULPI_DIGOUT_CTRL); }
static void ehci_msm_enable_ulpi_control(struct usb_hcd *hcd, u32 linestate) { struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd); int val; switch (linestate) { case PORT_RESET: val = ulpi_read(mehci, HSIC_DBG1); val |= ULPI_MANUAL_ENABLE; val &= ~(ULPI_LINESTATE_DATA | ULPI_LINESTATE_STROBE); ulpi_write(mehci, val, HSIC_DBG1); break; default: pr_info("%s: Unknown linestate:%0x\n", __func__, linestate); } }
static int msm_phy_notify_disconnect(struct usb_phy *phy, enum usb_device_speed speed) { int val; /* * Put the transceiver in non-driving mode. Otherwise host * may not detect soft-disconnection. */ val = ulpi_read(phy, ULPI_FUNC_CTRL); val &= ~ULPI_FUNC_CTRL_OPMODE_MASK; val |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING; ulpi_write(phy, val, ULPI_FUNC_CTRL); return 0; }
/* If this function returns < 0, the phy reset failed and we cannot * continue at this point. The only solution is to wait until the next * cable disconnect/reconnect to bring the phy back */ static int usb_phy_reset(struct usb_info *ui) { u32 val; int ret; int retries; if (!ui->phy_reset) return 0; if (ui->hw_reset) ui->hw_reset(1); ui->phy_reset(); if (ui->hw_reset) ui->hw_reset(0); #if defined(CONFIG_ARCH_QSD8X50) val = readl(USB_PORTSC) & ~PORTSC_PTS_MASK; writel(val | PORTSC_PTS_ULPI, USB_PORTSC); /* XXX: only necessary for pre-45nm internal PHYs. */ for (retries = 3; retries > 0; retries--) { ret = ulpi_write(ui, ULPI_FUNC_SUSPENDM, ULPI_FUNC_CTRL_CLR); if (!ret) break; ui->phy_reset(); } if (!retries) return -1; /* this reset calibrates the phy, if the above write succeeded */ ui->phy_reset(); /* XXX: pre-45nm internal phys have a known issue which can cause them * to lockup on reset. If ULPI accesses fail, try resetting the phy * again */ for (retries = 3; retries > 0; retries--) { ret = ulpi_read(ui, ULPI_DEBUG_REG); if (ret != 0xffffffff) break; ui->phy_reset(); } if (!retries) return -1; #endif pr_info("msm_hsusb_phy_reset: success\n"); return 0; }
static int msm_otg_remove(struct platform_device *pdev) { struct msm_otg *motg = platform_get_drvdata(pdev); struct usb_phy *phy = &motg->phy; int cnt = 0; if (phy->otg->host || phy->otg->gadget) return -EBUSY; msm_otg_debugfs_cleanup(); cancel_delayed_work_sync(&motg->chg_work); cancel_work_sync(&motg->sm_work); pm_runtime_resume(&pdev->dev); device_init_wakeup(&pdev->dev, 0); pm_runtime_disable(&pdev->dev); usb_remove_phy(phy); disable_irq(motg->irq); /* * Put PHY in low power mode. */ ulpi_read(phy, 0x14); ulpi_write(phy, 0x08, 0x09); writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC); while (cnt < PHY_SUSPEND_TIMEOUT_USEC) { if (readl(USB_PORTSC) & PORTSC_PHCD) break; udelay(1); cnt++; } if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) dev_err(phy->dev, "Unable to suspend PHY\n"); clk_disable_unprepare(motg->pclk); clk_disable_unprepare(motg->clk); if (!IS_ERR(motg->core_clk)) clk_disable_unprepare(motg->core_clk); msm_hsusb_ldo_init(motg, 0); pm_runtime_set_suspended(&pdev->dev); return 0; }
static unsigned msm_hsusb_ulpi_read_with_reset(void __iomem *usb_base, unsigned reg) { int temp; unsigned res; for (temp = 0; temp < ULPI_VERIFY_MAX_LOOP_COUNT; temp++) { res = ulpi_read(usb_base, reg); if (res != -1) return res; msm_hsusb_apps_reset_phy(); } pr_err("%s: ulpi read failed for %d times\n", __func__, ULPI_VERIFY_MAX_LOOP_COUNT); return -1; }
static int msm_otg_suspend(struct msm_otg *dev) { unsigned long timeout; int vbus = 0; disable_irq(dev->irq); if (dev->in_lpm) goto out; otg_reset(dev); ulpi_read(dev, 0x14);/* clear PHY interrupt latch register */ ulpi_write(dev, 0x01, 0x30);/* PHY comparators on in LPM */ ulpi_write(dev, 0x08, 0x09);/* turn off PLL on integrated phy */ timeout = jiffies + msecs_to_jiffies(500); disable_phy_clk(); while (!is_phy_clk_disabled()) { if (time_after(jiffies, timeout)) { pr_err("%s: Unable to suspend phy\n", __func__); otg_reset(dev); goto out; } msleep(1); } writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD); clk_disable(dev->clk); clk_disable(dev->pclk); if (device_may_wakeup(dev->otg.dev)) enable_irq_wake(dev->irq); dev->in_lpm = 1; /* TBD: as there is no bus suspend implemented as of now * it should be dummy check */ if (!vbus || release_wlocks) wake_unlock(&dev->wlock); pr_info("%s: usb in low power mode\n", __func__); out: enable_irq(dev->irq); return 0; }
static int msm_hsusb_phy_verify_access(void __iomem *usb_base) { int temp; for (temp = 0; temp < ULPI_VERIFY_MAX_LOOP_COUNT; temp++) { if (ulpi_read(usb_base, ULPI_DEBUG) != (unsigned)-1) break; msm_hsusb_apps_reset_phy(); } if (temp == ULPI_VERIFY_MAX_LOOP_COUNT) { pr_err("%s: ulpi read failed for %d times\n", __func__, ULPI_VERIFY_MAX_LOOP_COUNT); return -1; } return 0; }
static void msm_chg_disable_dcd(struct msm_otg *motg) { struct usb_phy *phy = &motg->phy; u32 chg_det; switch (motg->pdata->phy_type) { case CI_45NM_INTEGRATED_PHY: chg_det = ulpi_read(phy, 0x34); chg_det &= ~(1 << 5); ulpi_write(phy, chg_det, 0x34); break; case SNPS_28NM_INTEGRATED_PHY: ulpi_write(phy, 0x10, 0x86); break; default: break; } }
static unsigned ulpi_read_with_reset(struct msm_otg *dev, unsigned reg) { int temp; unsigned res; for (temp = 0; temp < ULPI_VERIFY_MAX_LOOP_COUNT; temp++) { res = ulpi_read(dev, reg); if (res != 0xffffffff) return res; phy_clk_reset(dev); } pr_err("%s: ulpi read failed for %d times\n", __func__, ULPI_VERIFY_MAX_LOOP_COUNT); return -1; }