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->phy_number) writel(readl(USB_PHY_CTRL2) | BIT(16), USB_PHY_CTRL2); return 0; }
static void msm_otg_host_notify(struct msm_otg *motg, int on) { if (on) msm_otg_host_phy_tune(motg, 0x33, 0x14, 0x13); else ulpi_init(motg); }
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 msm_otg_reset(struct otg_transceiver *otg) { struct msm_otg *motg = container_of(otg, struct msm_otg, otg); struct msm_otg_platform_data *pdata = motg->pdata; int cnt = 0; int ret; u32 val = 0; u32 ulpi_val = 0; ret = msm_otg_phy_reset(motg); if (ret) { dev_err(otg->dev, "phy_reset failed\n"); return ret; } ulpi_init(motg); writel(USBCMD_RESET, USB_USBCMD); while (cnt < LINK_RESET_TIMEOUT_USEC) { if (!(readl(USB_USBCMD) & USBCMD_RESET)) break; udelay(1); cnt++; } if (cnt >= LINK_RESET_TIMEOUT_USEC) return -ETIMEDOUT; /* select ULPI phy */ writel(0x80000000, USB_PORTSC); msleep(100); writel(0x0, USB_AHBBURST); writel(0x00, USB_AHBMODE); if (pdata->otg_control == OTG_PHY_CONTROL) { val = readl(USB_OTGSC); if (pdata->mode == USB_OTG) { ulpi_val = ULPI_INT_IDGRD | ULPI_INT_SESS_VALID; val |= OTGSC_IDIE | OTGSC_BSVIE; } else if (pdata->mode == USB_PERIPHERAL) { ulpi_val = ULPI_INT_SESS_VALID; val |= OTGSC_BSVIE; } writel(val, USB_OTGSC); ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_RISE); ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_FALL); } return 0; }
static void efika_ehci_init(struct usb_ehci *ehci, uint32_t stp_gpio, uint32_t alt0, uint32_t alt1) { int ret; struct ulpi_regs *ulpi = (struct ulpi_regs *)0; struct ulpi_viewport ulpi_vp; mxc_request_iomux(stp_gpio, alt0); mxc_iomux_set_pad(stp_gpio, PAD_CTL_DRV_HIGH | PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST); gpio_direction_output(IOMUX_TO_GPIO(stp_gpio), 0); udelay(1000); gpio_set_value(IOMUX_TO_GPIO(stp_gpio), 1); udelay(1000); mxc_request_iomux(stp_gpio, alt1); mxc_iomux_set_pad(stp_gpio, USB_PAD_CONFIG); udelay(10000); ulpi_vp.viewport_addr = (u32)&ehci->ulpi_viewpoint; ulpi_vp.port_num = 0; ret = ulpi_init(&ulpi_vp); if (ret) { printf("Efika USB ULPI initialization failed\n"); return; } /* ULPI set flags */ ulpi_write(&ulpi_vp, &ulpi->otg_ctrl, ULPI_OTG_DP_PULLDOWN | ULPI_OTG_DM_PULLDOWN | ULPI_OTG_EXTVBUSIND); ulpi_write(&ulpi_vp, &ulpi->function_ctrl, ULPI_FC_FULL_SPEED | ULPI_FC_OPMODE_NORMAL | ULPI_FC_SUSPENDM); ulpi_write(&ulpi_vp, &ulpi->iface_ctrl, 0); /* Set VBus */ ulpi_write(&ulpi_vp, &ulpi->otg_ctrl_set, ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT); /* * Set VBusChrg * * NOTE: This violates USB specification, but otherwise, USB on Efika * doesn't work. */ ulpi_write(&ulpi_vp, &ulpi->otg_ctrl_set, ULPI_OTG_CHRGVBUS); }
static int ehci_zynq_probe(struct udevice *dev) { struct usb_platdata *plat = dev_get_platdata(dev); struct zynq_ehci_priv *priv = dev_get_priv(dev); struct ehci_hccr *hccr; struct ehci_hcor *hcor; struct ulpi_viewport ulpi_vp; /* Used for writing the ULPI data address */ struct ulpi_regs *ulpi = (struct ulpi_regs *)0; int ret; hccr = (struct ehci_hccr *)((uint32_t)&priv->ehci->caplength); hcor = (struct ehci_hcor *)((uint32_t) hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase))); ulpi_vp.viewport_addr = (u32)&priv->ehci->ulpi_viewpoint; ulpi_vp.port_num = 0; ret = ulpi_init(&ulpi_vp); if (ret) { puts("zynq ULPI viewport init failed\n"); return -1; } /* ULPI set flags */ ulpi_write(&ulpi_vp, &ulpi->otg_ctrl, ULPI_OTG_DP_PULLDOWN | ULPI_OTG_DM_PULLDOWN | ULPI_OTG_EXTVBUSIND); ulpi_write(&ulpi_vp, &ulpi->function_ctrl, ULPI_FC_FULL_SPEED | ULPI_FC_OPMODE_NORMAL | ULPI_FC_SUSPENDM); ulpi_write(&ulpi_vp, &ulpi->iface_ctrl, 0); /* Set VBus */ ulpi_write(&ulpi_vp, &ulpi->otg_ctrl_set, ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT); return ehci_register(dev, hccr, hcor, NULL, 0, plat->init_type); }
/* set up the ULPI USB controller with the parameters provided */ static int init_ulpi_usb_controller(struct fdt_usb *config, struct usb_ctlr *usbctlr) { u32 val; int loop_count; struct ulpi_viewport ulpi_vp; /* set up ULPI reference clock on pllp_out4 */ clock_enable(PERIPH_ID_DEV2_OUT); clock_set_pllout(CLOCK_ID_PERIPH, PLL_OUT4, CONFIG_ULPI_REF_CLK); /* reset ULPI phy */ if (fdt_gpio_isvalid(&config->phy_reset_gpio)) { fdtdec_setup_gpio(&config->phy_reset_gpio); gpio_direction_output(config->phy_reset_gpio.gpio, 0); mdelay(5); gpio_set_value(config->phy_reset_gpio.gpio, 1); } /* Reset the usb controller */ clock_enable(config->periph_id); usbf_reset_controller(config, usbctlr); /* enable pinmux bypass */ setbits_le32(&usbctlr->ulpi_timing_ctrl_0, ULPI_CLKOUT_PINMUX_BYP | ULPI_OUTPUT_PINMUX_BYP); /* Select ULPI parallel interface */ clrsetbits_le32(&usbctlr->port_sc1, PTS_MASK, PTS_ULPI << PTS_SHIFT); /* enable ULPI transceiver */ setbits_le32(&usbctlr->susp_ctrl, ULPI_PHY_ENB); /* configure ULPI transceiver timings */ val = 0; writel(val, &usbctlr->ulpi_timing_ctrl_1); val |= ULPI_DATA_TRIMMER_SEL(4); val |= ULPI_STPDIRNXT_TRIMMER_SEL(4); val |= ULPI_DIR_TRIMMER_SEL(4); writel(val, &usbctlr->ulpi_timing_ctrl_1); udelay(10); val |= ULPI_DATA_TRIMMER_LOAD; val |= ULPI_STPDIRNXT_TRIMMER_LOAD; val |= ULPI_DIR_TRIMMER_LOAD; writel(val, &usbctlr->ulpi_timing_ctrl_1); /* set up phy for host operation with external vbus supply */ ulpi_vp.port_num = 0; ulpi_vp.viewport_addr = (u32)&usbctlr->ulpi_viewport; if (ulpi_init(&ulpi_vp)) { printf("Tegra ULPI viewport init failed\n"); return -1; } ulpi_set_vbus(&ulpi_vp, 1, 1); ulpi_set_vbus_indicator(&ulpi_vp, 1, 1, 0); /* enable wakeup events */ setbits_le32(&usbctlr->port_sc1, WKCN | WKDS | WKOC); /* Enable and wait for the phy clock to become valid in 100 ms */ setbits_le32(&usbctlr->susp_ctrl, USB_SUSP_CLR); for (loop_count = 100000; loop_count != 0; loop_count--) { if (readl(&usbctlr->susp_ctrl) & USB_PHY_CLK_VALID) break; udelay(1); } if (!loop_count) return -1; clrbits_le32(&usbctlr->susp_ctrl, USB_SUSP_CLR); return 0; }
static void usb_reset(struct usb_info *ui) { unsigned long flags; printk(KERN_INFO "hsusb: reset controller\n"); spin_lock_irqsave(&ui->lock, flags); ui->running = 0; spin_unlock_irqrestore(&ui->lock, flags); /* To prevent phantom packets being received by the usb core on * some devices, put the controller into reset prior to * resetting the phy. */ writel(2, USB_USBCMD); msleep(10); #if 0 /* we should flush and shutdown cleanly if already running */ writel(0xffffffff, USB_ENDPTFLUSH); msleep(2); #endif if (usb_phy_reset(ui) < 0) pr_err("%s: Phy reset failed!\n", __func__); msleep(100); /* toggle non-driving mode after phy reset to ensure that * we cause a disconnect event to the host */ ulpi_write(ui, 0x18, 0x6); msleep(1); ulpi_write(ui, 0x8, 0x5); msleep(1); /* RESET */ writel(2, USB_USBCMD); msleep(10); #ifdef CONFIG_ARCH_MSM7X00A /* INCR4 BURST mode */ writel(0x01, USB_SBUSCFG); #else /* bursts of unspecified length. */ writel(0, USB_AHBBURST); /* Use the AHB transactor */ writel(0, USB_AHBMODE); #endif /* select DEVICE mode */ writel(0x12, USB_USBMODE); msleep(1); /* select ULPI phy */ writel(0x80000000, USB_PORTSC); ulpi_init(ui); writel(ui->dma, USB_ENDPOINTLISTADDR); configure_endpoints(ui); /* marking us offline will cause ept queue attempts to fail */ ui->online = 0; /* terminate any pending transactions */ flush_all_endpoints(ui); if (ui->driver) { printk(KERN_INFO "usb: notify offline\n"); ui->driver->disconnect(&ui->gadget); } /* enable interrupts */ writel(STS_URI | STS_SLI | STS_UI | STS_PCI, USB_USBINTR); /* go to RUN mode (D+ pullup enable) */ msm72k_pullup(&ui->gadget, 1); spin_lock_irqsave(&ui->lock, flags); ui->running = 1; spin_unlock_irqrestore(&ui->lock, flags); }
static void usb_reset(struct usb_info *ui) { unsigned long flags; unsigned cfg_val; unsigned otgsc; INFO("msm72k_udc: reset controller\n"); spin_lock_irqsave(&ui->lock, flags); ui->running = 0; spin_unlock_irqrestore(&ui->lock, flags); #if 0 /* we should flush and shutdown cleanly if already running */ writel(0xffffffff, USB_ENDPTFLUSH); msleep(2); #endif otgsc = readl(USB_OTGSC); /* RESET */ writel(2, USB_USBCMD); msleep(10); if (ui->phy_reset) ui->phy_reset(); /* select DEVICE mode */ writel(0x12, USB_USBMODE); msleep(1); /* select ULPI phy */ writel(0x80000000, USB_PORTSC); /* electrical compliance failure in eye-diagram tests * were observed w/ integrated phy. To avoid failure * raise signal amplitude to 400mv */ cfg_val = ulpi_read(ui, ULPI_CONFIG_REG); cfg_val |= ULPI_AMPLITUDE_MAX; ulpi_write(ui, cfg_val, ULPI_CONFIG_REG); /* fix potential usb stability issues with "integrated phy" * by enabling unspecified length of INCR burst and using * the AHB master interface of the AHB2AHB transactor */ writel(0, USB_AHB_BURST); writel(0, USB_AHB_MODE); ulpi_init(ui); writel(ui->dma, USB_ENDPOINTLISTADDR); configure_endpoints(ui); /* marking us offline will cause ept queue attempts to fail */ ui->online = 0; /* terminate any pending transactions */ flush_all_endpoints(ui); if (ui->driver) { printk(KERN_INFO "usb: notify offline\n"); ui->driver->disconnect(&ui->gadget); } /* enable interrupts */ writel(otgsc, USB_OTGSC); writel(STS_URI | STS_SLI | STS_UI | STS_PCI, USB_USBINTR); spin_lock_irqsave(&ui->lock, flags); ui->running = 1; spin_unlock_irqrestore(&ui->lock, flags); }