コード例 #1
0
ファイル: init.c プロジェクト: sztablet2016/Android-kernel-lk
void target_usb_init(void)
{
	uint32_t val;

	/* Select and enable external configuration with USB PHY */
	ulpi_write(ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT, ULPI_MISC_A_SET);

	/* Enable sess_vld */
	val = readl(USB_GENCONFIG_2) | GEN2_SESS_VLD_CTRL_EN;
	writel(val, USB_GENCONFIG_2);

	/* Enable external vbus configuration in the LINK */
	val = readl(USB_USBCMD);
	val |= SESS_VLD_CTRL;
	writel(val, USB_USBCMD);
}
コード例 #2
0
ファイル: phy-msm-usb.c プロジェクト: AkyZero/wrapfs-latest
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;
}
コード例 #3
0
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);
	}
}
コード例 #4
0
static void msm7201_setup_phy(struct usb_hcd *hcd)
{
/*	struct msm7201_usb_priv *msm7201 = hcd_to_msm7201(hcd);

  int *seq = msm7201->phy_init_seq;

	if (!seq)
		return;*/
  static int seq[] = { 0x40, 0x31, 0x1D, 0x0D, 0x1D, 0x10, -1 };

	int p=0;
	while (seq[p] >= 0) {
		ulpi_write(hcd, seq[p], seq[p+1]);
		p += 2;
	}
}
コード例 #5
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;
}
コード例 #6
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;
}
コード例 #7
0
ファイル: devices.c プロジェクト: RuNuH/Glacier-HTC2
static int msm_hsusb_ulpi_write_with_reset(void __iomem *usb_base,
		unsigned val, unsigned reg)
{
	int temp;
	int res;

	for (temp = 0; temp < ULPI_VERIFY_MAX_LOOP_COUNT; temp++) {
		res = ulpi_write(usb_base, val, reg);
		if (!res)
			return 0;
		msm_hsusb_apps_reset_phy();
	}

	pr_err("%s: ulpi write failed for %d times\n",
			__func__, ULPI_VERIFY_MAX_LOOP_COUNT);
	return -1;
}
コード例 #8
0
ファイル: init.c プロジェクト: nx511j-multirom/bootloader_lk
/* Do target specific usb initialization */
void target_usb_init(void)
{
	uint32_t val;

	/* Enable secondary USB PHY on DragonBoard8074 */
	if (board_hardware_id() == HW_PLATFORM_DRAGON) {
		/* Route ChipIDea to use secondary USB HS port2 */
		writel_relaxed(1, USB2_PHY_SEL);

		/* Enable access to secondary PHY by clamping the low
		* voltage interface between DVDD of the PHY and Vddcx
		* (set bit16 (USB2_PHY_HS2_DIG_CLAMP_N_2) = 1) */
		writel_relaxed(readl_relaxed(USB_OTG_HS_PHY_SEC_CTRL)
				| 0x00010000, USB_OTG_HS_PHY_SEC_CTRL);

		/* Perform power-on-reset of the PHY.
		*  Delay values are arbitrary */
		writel_relaxed(readl_relaxed(USB_OTG_HS_PHY_CTRL)|1,
				USB_OTG_HS_PHY_CTRL);
		thread_sleep(10);
		writel_relaxed(readl_relaxed(USB_OTG_HS_PHY_CTRL) & 0xFFFFFFFE,
				USB_OTG_HS_PHY_CTRL);
		thread_sleep(10);

		/* Enable HSUSB PHY port for ULPI interface,
		* then configure related parameters within the PHY */
		writel_relaxed(((readl_relaxed(USB_PORTSC) & 0xC0000000)
				| 0x8c000004), USB_PORTSC);
	}

	if (target_needs_vbus_mimic())
	{
		/* Select and enable external configuration with USB PHY */
		ulpi_write(ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT, ULPI_MISC_A_SET);

		/* Enable sess_vld */
		val = readl(USB_GENCONFIG_2) | GEN2_SESS_VLD_CTRL_EN;
		writel(val, USB_GENCONFIG_2);

		/* Enable external vbus configuration in the LINK */
		val = readl(USB_USBCMD);
		val |= SESS_VLD_CTRL;
		writel(val, USB_USBCMD);
	}
}
コード例 #9
0
ファイル: efikamx-usb.c プロジェクト: AeroGirl/u-boot-kern3.2
void ehci_powerup_fixup(uint32_t *status_reg, uint32_t *reg)
{
	uint32_t port = OTG_BASE_ADDR + (0x200 * CONFIG_MXC_USB_PORT);
	struct usb_ehci *ehci = (struct usb_ehci *)port;
	struct ulpi_regs *ulpi = (struct ulpi_regs *)0;
	struct ulpi_viewport ulpi_vp;

	ulpi_vp.viewport_addr = (u32)&ehci->ulpi_viewpoint;
	ulpi_vp.port_num = 0;

	ulpi_write(&ulpi_vp, &ulpi->otg_ctrl_set, ULPI_OTG_CHRGVBUS);

	mdelay(50);

	/* terminate the reset */
	*reg = ehci_readl(status_reg);
	*reg |= EHCI_PS_PE;
}
コード例 #10
0
ファイル: phy-msm-usb.c プロジェクト: guanhe0/kernel
static void msm_chg_enable_secondary_det(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);
		/* Turn off charger block */
		chg_det |= ~(1 << 1);
		ulpi_write(phy, chg_det, 0x34);
		udelay(20);
		/* control chg block via ULPI */
		chg_det &= ~(1 << 3);
		ulpi_write(phy, chg_det, 0x34);
		/* put it in host mode for enabling D- source */
		chg_det &= ~(1 << 2);
		ulpi_write(phy, chg_det, 0x34);
		/* Turn on chg detect block */
		chg_det &= ~(1 << 1);
		ulpi_write(phy, chg_det, 0x34);
		udelay(20);
		/* enable chg detection */
		chg_det &= ~(1 << 0);
		ulpi_write(phy, chg_det, 0x34);
		break;
	case SNPS_28NM_INTEGRATED_PHY:
		/*
		 * Configure DM as current source, DP as current sink
		 * and enable battery charging comparators.
		 */
		ulpi_write(phy, 0x8, 0x85);
		ulpi_write(phy, 0x2, 0x85);
		ulpi_write(phy, 0x1, 0x85);
		break;
	default:
		break;
	}
}
コード例 #11
0
/* drivers may have software control over D+ pullup */
static int msm72k_pullup(struct usb_gadget *_gadget, int is_active)
{
	struct usb_info *ui = container_of(_gadget, struct usb_info, gadget);

	u32 cmd = (8 << 16);

	/* disable/enable D+ pullup */
	if (is_active) {
		pr_info("msm_hsusb: enable pullup\n");
		writel(cmd | 1, USB_USBCMD);
	} else {
		pr_info("msm_hsusb: disable pullup\n");
		writel(cmd, USB_USBCMD);

#if defined(CONFIG_ARCH_QSD8X50) || defined(CONFIG_ARCH_MSM7X30)
		ulpi_write(ui, 0x48, 0x04);
#endif
	}

	return 0;
}
コード例 #12
0
ファイル: ulpi.c プロジェクト: lovejavaee/linux-2
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;
}
コード例 #13
0
ファイル: phy-msm-usb.c プロジェクト: guanhe0/kernel
static int msm_phy_notify_disconnect(struct usb_phy *phy,
				   enum usb_device_speed speed)
{
	struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
	int val;

	if (motg->manual_pullup) {
		val = ULPI_MISC_A_VBUSVLDEXT | ULPI_MISC_A_VBUSVLDEXTSEL;
		usb_phy_io_write(phy, val, ULPI_CLR(ULPI_MISC_A));
	}

	/*
	 * 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;
}
コード例 #14
0
ファイル: zynq_usb.c プロジェクト: yazshel/netbsd-kernel
static void
ulpi_reset(struct zynqehci_softc *sc)
{
	uint8_t data;
	int timo = 1000 * 1000;	/* XXXX: 1sec */

	ulpi_write(sc, ULPI_FUNCTION_CONTROL + ULPI_REG_SET,
	    FUNCTION_CONTROL_RESET /*0x20*/);
	do {
		data = ulpi_read(sc, ULPI_FUNCTION_CONTROL);
		if (!(data & FUNCTION_CONTROL_RESET))
			break;
		delay(100);
		timo -= 100;
	} while (timo > 0);
	if (timo <= 0) {
		aprint_error_dev(sc->sc_hsc.sc_dev, "%s: reset failed!!\n",
		    __func__);
		return;
	}

	return;
}
コード例 #15
0
static void disable_idgnd(struct msm_otg *dev)
{
	ulpi_write(dev, (1<<4), 0x0F);
	ulpi_write(dev, (1<<4), 0x12);
	writel(readl(USB_OTGSC) & ~OTGSC_IDIE, USB_OTGSC);
}
コード例 #16
0
static void enable_idgnd(struct msm_otg *dev)
{
	ulpi_write(dev, (1<<4), 0x0E);
	ulpi_write(dev, (1<<4), 0x11);
	writel(readl(USB_OTGSC) | OTGSC_IDIE, USB_OTGSC);
}
コード例 #17
0
static void disable_sess_valid(struct msm_otg *dev)
{
	ulpi_write(dev, (1<<2), 0x0F);
	ulpi_write(dev, (1<<2), 0x12);
	writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC);
}
コード例 #18
0
static void enable_sess_valid(struct msm_otg *dev)
{
	ulpi_write(dev, (1<<2), 0x0E);
	ulpi_write(dev, (1<<2), 0x11);
	writel(readl(USB_OTGSC) | OTGSC_BSVIE, USB_OTGSC);
}
コード例 #19
0
static int msm_hsic_reset(struct msm_hsic_hcd *mehci)
{
	struct usb_hcd *hcd = hsic_to_hcd(mehci);
	int ret;
	struct msm_hsic_host_platform_data *pdata = mehci->dev->platform_data;

	msm_hsic_clk_reset(mehci);

	/* select ulpi phy */
	writel_relaxed(0x80000000, USB_PORTSC);

	mb();

	/* HSIC init sequence when HSIC signals (Strobe/Data) are
	routed via GPIOs */
	if (pdata && pdata->strobe && pdata->data) {

		/* Enable LV_MODE in HSIC_CAL_PAD_CTL register */
		writel_relaxed(HSIC_LV_MODE, HSIC_CAL_PAD_CTL);

		mb();

		/*set periodic calibration interval to ~2.048sec in
		  HSIC_IO_CAL_REG */
		ulpi_write(mehci, 0xFF, 0x33);

		/* Enable periodic IO calibration in HSIC_CFG register */
		ulpi_write(mehci, HSIC_PAD_CALIBRATION, 0x30);

		/* Configure GPIO pins for HSIC functionality mode */
		ret = msm_hsic_config_gpios(mehci, 1);
		if (ret) {
			dev_err(mehci->dev, " gpio configuarion failed\n");
			return ret;
		}
		/* Set LV_MODE=0x1 and DCC=0x2 in HSIC_GPIO PAD_CTL register */
		writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_STROBE_GPIO_PAD_CTL);
		writel_relaxed(HSIC_GPIO_PAD_VAL, HSIC_DATA_GPIO_PAD_CTL);

		mb();

		/* Enable HSIC mode in HSIC_CFG register */
		ulpi_write(mehci, 0x01, 0x31);
	} else {
		/* HSIC init sequence when HSIC signals (Strobe/Data) are routed
		via dedicated I/O */

		/* programmable length of connect signaling (33.2ns) */
		ret = ulpi_write(mehci, 3, HSIC_DBG1_REG);
		if (ret) {
			pr_err("%s: Unable to program length of connect "
			      "signaling\n", __func__);
		}

		/*set periodic calibration interval to ~2.048sec in
		  HSIC_IO_CAL_REG */
		ulpi_write(mehci, 0xFF, 0x33);

		/* Enable HSIC mode in HSIC_CFG register */
		ulpi_write(mehci, 0xA9, 0x30);
	}

	/*disable auto resume*/
	ulpi_write(mehci, ULPI_IFC_CTRL_AUTORESUME, ULPI_CLR(ULPI_IFC_CTRL));

	return 0;
}
コード例 #20
0
ファイル: imxusb.c プロジェクト: yazshel/netbsd-kernel
static void
imxehci_attach(device_t parent, device_t self, void *aux)
{
	struct imxusbc_attach_args *aa = aux;
	struct imxusbc_softc *usbc = device_private(parent);
	struct imxehci_softc *sc = device_private(self);
	ehci_softc_t *hsc = &sc->sc_hsc;
	bus_space_tag_t iot;
	uint16_t hcirev;
	usbd_status r;
	uint32_t id, hwhost, hwdevice;
	const char *comma;

	sc->sc_hsc.sc_dev = self;
	iot = sc->sc_iot = sc->sc_hsc.iot = aa->aa_iot;
	sc->sc_unit = aa->aa_unit;
	sc->sc_usbc = usbc;
	hsc->sc_bus.hci_private = sc;
	hsc->sc_flags |= EHCIF_ETTF;
	hsc->sc_vendor_init = imxehci_init;

	aprint_naive("\n");
	aprint_normal(": i.MX USB Controller\n");

	/* per unit registers */
	if (bus_space_subregion(iot, aa->aa_ioh,
		aa->aa_unit * IMXUSB_EHCI_SIZE, IMXUSB_EHCI_SIZE,
		&sc->sc_ioh) ||
	    bus_space_subregion(iot, aa->aa_ioh,
		aa->aa_unit * IMXUSB_EHCI_SIZE + IMXUSB_EHCIREGS,
		IMXUSB_EHCI_SIZE - IMXUSB_EHCIREGS,
		&sc->sc_hsc.ioh)) {

		aprint_error_dev(self, "can't subregion\n");
		return;
	}

	id = bus_space_read_4(iot, sc->sc_ioh, IMXUSB_ID);
	hcirev = bus_space_read_2(iot, sc->sc_hsc.ioh, EHCI_HCIVERSION);

	aprint_normal_dev(self,
	    "id=%d revision=%d HCI revision=0x%x\n",
	    (int)__SHIFTOUT(id, IMXUSB_ID_ID),
	    (int)__SHIFTOUT(id, IMXUSB_ID_REVISION),
	    hcirev);

	hwhost = bus_space_read_4(iot, sc->sc_ioh, IMXUSB_HWHOST);
	hwdevice = bus_space_read_4(iot, sc->sc_ioh, IMXUSB_HWDEVICE);

	aprint_normal_dev(self, "");

	comma = "";
	if (hwhost & HWHOST_HC) {
		int n_ports = 1 + __SHIFTOUT(hwhost, HWHOST_NPORT);
		aprint_normal("%d host port%s",
		    n_ports, n_ports > 1 ? "s" : "");
		comma = ", ";
	}

	if (hwdevice & HWDEVICE_DC) {
		int n_endpoints = __SHIFTOUT(hwdevice, HWDEVICE_DEVEP);
		aprint_normal("%sdevice capable, %d endpoint%s",
		    comma,
		    n_endpoints, n_endpoints > 1 ? "s" : "");
	}
	aprint_normal("\n");

	sc->sc_hsc.sc_bus.dmatag = aa->aa_dmat;

	sc->sc_hsc.sc_offs = bus_space_read_1(iot, sc->sc_hsc.ioh,
	    EHCI_CAPLENGTH);

	/* Platform dependent setup */
	if (usbc->sc_init_md_hook)
		usbc->sc_init_md_hook(sc);
	
	imxehci_reset(sc);
	imxehci_select_interface(sc, sc->sc_iftype);

	if (sc->sc_iftype == IMXUSBC_IF_ULPI) {
		bus_space_write_4(sc->sc_iot, sc->sc_ioh, IMXUSB_ULPIVIEW, 0);

		aprint_normal_dev(hsc->sc_dev,
		    "ULPI phy VID 0x%04x PID 0x%04x\n",
		    (imxusb_ulpi_read(sc, ULPI_VENDOR_ID_LOW) |
			imxusb_ulpi_read(sc, ULPI_VENDOR_ID_HIGH) << 8),
		    (imxusb_ulpi_read(sc, ULPI_PRODUCT_ID_LOW) |
			imxusb_ulpi_read(sc, ULPI_PRODUCT_ID_HIGH) << 8));

		ulpi_reset(sc);

	}

	if (usbc->sc_setup_md_hook)
		usbc->sc_setup_md_hook(sc, IMXUSB_HOST);

	if (sc->sc_iftype == IMXUSBC_IF_ULPI) {
#if 0
		if(hsc->sc_bus.usbrev == USBREV_2_0)
			ulpi_write(hsc, ULPI_FUNCTION_CONTROL + ULPI_REG_CLEAR, (1 << 0));
		else
			ulpi_write(hsc, ULPI_FUNCTION_CONTROL + ULPI_REG_SET, (1 << 2));
#endif

		imxusb_ulpi_write(sc, ULPI_FUNCTION_CONTROL + ULPI_REG_CLEAR,
		    OTG_CONTROL_IDPULLUP);

		imxusb_ulpi_write(sc, ULPI_OTG_CONTROL + ULPI_REG_SET,
		    OTG_CONTROL_USEEXTVBUSIND |
		    OTG_CONTROL_DRVVBUSEXT |
		    OTG_CONTROL_DRVVBUS |
		    OTG_CONTROL_CHRGVBUS
		    );
	}

	/* Disable interrupts, so we don't get any spurious ones. */
	EOWRITE4(hsc, EHCI_USBINTR, 0);

	intr_establish(aa->aa_irq, IPL_USB, IST_LEVEL, ehci_intr, hsc);

	/* Figure out vendor for root hub descriptor. */
	strlcpy(hsc->sc_vendor, "i.MX", sizeof(hsc->sc_vendor));

	r = ehci_init(hsc);
	if (r != USBD_NORMAL_COMPLETION) {
		aprint_error_dev(self, "init failed, error=%d\n", r);
		return;
	}

	/* Attach usb device. */
	hsc->sc_child = config_found(self, &hsc->sc_bus, usbctlprint);
}
コード例 #21
0
ファイル: zynq_usb.c プロジェクト: yazshel/netbsd-kernel
void
zynqusb_attach_common(device_t parent, device_t self, bus_space_tag_t iot,
    bus_dma_tag_t dmat, paddr_t iobase, size_t size, int intr, int flags,
    enum zynq_usb_if type, enum zynq_usb_role role)
{
	struct zynqehci_softc *sc = device_private(self);
	ehci_softc_t *hsc = &sc->sc_hsc;
	uint16_t hcirev;
	usbd_status r;
	uint32_t id, hwhost, hwdevice;
	const char *comma;

	sc->sc_hsc.sc_dev = self;
	sc->sc_iot = sc->sc_hsc.iot = iot;
	sc->sc_iftype = type;
	sc->sc_role = role;

	hsc->sc_bus.hci_private = sc;
	hsc->sc_bus.usbrev = USBREV_2_0;
	hsc->sc_flags |= EHCIF_ETTF;
	hsc->sc_vendor_init = zynqusb_init;

	aprint_normal("\n");

	if (bus_space_map(iot, iobase, size, 0, &sc->sc_ioh)) {

		aprint_error_dev(self, "unable to map device\n");
		return;
	}

	if (bus_space_subregion(iot, sc->sc_ioh,
		ZYNQUSB_EHCIREGS, ZYNQUSB_EHCI_SIZE - ZYNQUSB_EHCIREGS,
		&sc->sc_hsc.ioh)) {

		aprint_error_dev(self, "unable to map subregion\n");
		return;
	}

	id = bus_space_read_4(iot, sc->sc_ioh, ZYNQUSB_ID);
	hcirev = bus_space_read_2(iot, sc->sc_hsc.ioh, EHCI_HCIVERSION);

	aprint_normal_dev(self,
	    "Zynq USB Controller id=%d revision=%d version=%d\n",
	    (int)__SHIFTOUT(id, ZYNQUSB_ID_ID),
	    (int)__SHIFTOUT(id, ZYNQUSB_ID_REVISION),
	    (int)__SHIFTOUT(id, ZYNQUSB_ID_VERSION));
	aprint_normal_dev(self, "HCI revision=0x%x\n", hcirev);

	hwhost = bus_space_read_4(iot, sc->sc_ioh, ZYNQUSB_HWHOST);
	hwdevice = bus_space_read_4(iot, sc->sc_ioh, ZYNQUSB_HWDEVICE);

	aprint_normal_dev(self, "");

	comma = "";
	if (hwhost & HWHOST_HC) {
		int n_ports = 1 + __SHIFTOUT(hwhost, HWHOST_NPORT);
		aprint_normal("%d host port%s",
		    n_ports, n_ports > 1 ? "s" : "");
		comma = ", ";
	}

	if (hwdevice & HWDEVICE_DC) {
		int n_endpoints = __SHIFTOUT(hwdevice, HWDEVICE_DEVEP);
		aprint_normal("%sdevice capable, %d endpoint%s",
		    comma,
		    n_endpoints, n_endpoints > 1 ? "s" : "");
	}
	aprint_normal("\n");

	sc->sc_hsc.sc_bus.dmatag = dmat;

	sc->sc_hsc.sc_offs = bus_space_read_1(iot, sc->sc_hsc.ioh,
	    EHCI_CAPLENGTH);

	zynqusb_reset(sc);
	zynqusb_select_interface(sc, sc->sc_iftype);

	if (sc->sc_iftype == ZYNQUSBC_IF_ULPI) {
		bus_space_write_4(sc->sc_iot, sc->sc_ioh, ZYNQUSB_ULPIVIEW, 0);

		aprint_normal_dev(hsc->sc_dev,
		    "ULPI phy VID 0x%04x PID 0x%04x\n",
		    (ulpi_read(sc, ULPI_VENDOR_ID_LOW) |
			ulpi_read(sc, ULPI_VENDOR_ID_HIGH) << 8),
		    (ulpi_read(sc, ULPI_PRODUCT_ID_LOW) |
			ulpi_read(sc, ULPI_PRODUCT_ID_HIGH) << 8));

		ulpi_reset(sc);
	}

	if (sc->sc_iftype == ZYNQUSBC_IF_ULPI) {
		if(hsc->sc_bus.usbrev == USBREV_2_0) {
			ulpi_write(sc, ULPI_FUNCTION_CONTROL + ULPI_REG_CLEAR,
			    FUNCTION_CONTROL_XCVRSELECT);
			ulpi_write(sc, ULPI_FUNCTION_CONTROL + ULPI_REG_SET,
			    FUNCTION_CONTROL_TERMSELECT);
		} else {
			ulpi_write(sc, ULPI_FUNCTION_CONTROL + ULPI_REG_SET,
			    XCVRSELECT_FSLS);
			ulpi_write(sc, ULPI_FUNCTION_CONTROL + ULPI_REG_CLEAR,
			    FUNCTION_CONTROL_TERMSELECT);
		}

		ulpi_write(sc, ULPI_OTG_CONTROL + ULPI_REG_SET,
		    OTG_CONTROL_USEEXTVBUSIND |
		    OTG_CONTROL_DRVVBUSEXT |
		    OTG_CONTROL_DRVVBUS |
		    OTG_CONTROL_CHRGVBUS);
	}

	/* Disable interrupts, so we don't get any spurious ones. */
	EOWRITE4(hsc, EHCI_USBINTR, 0);

	intr_establish(intr, IPL_USB, IST_LEVEL, ehci_intr, hsc);

	/* Figure out vendor for root hub descriptor. */
	strlcpy(hsc->sc_vendor, "Xilinx", sizeof(hsc->sc_vendor));

	r = ehci_init(hsc);
	if (r != USBD_NORMAL_COMPLETION) {
		aprint_error_dev(self, "init failed, error=%d\n", r);
		return;
	}

	/* Attach usb device. */
	hsc->sc_child = config_found(self, &hsc->sc_bus, usbctlprint);
}
コード例 #22
0
ファイル: init.c プロジェクト: detule/lk-g2-spr
void target_usb_stop(void)
{
	/* Disable VBUS mimicing in the controller. */
	ulpi_write(ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT, ULPI_MISC_A_CLEAR);
}
コード例 #23
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);
}
コード例 #24
0
ファイル: ehci-msm.c プロジェクト: OpenNoah/u-boot
static void setup_usb_phy(struct msm_ehci_priv *priv)
{
	/* Select and enable external configuration with USB PHY */
	ulpi_write(&priv->ulpi_vp, (u8 *)ULPI_MISC_A_SET,
		   ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT);
}
コード例 #25
0
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);
}
コード例 #26
0
ファイル: phy-msm-usb.c プロジェクト: guanhe0/kernel
static int msm_otg_suspend(struct msm_otg *motg)
{
	struct usb_phy *phy = &motg->phy;
	struct usb_bus *bus = phy->otg->host;
	struct msm_otg_platform_data *pdata = motg->pdata;
	void __iomem *addr;
	int cnt = 0;

	if (atomic_read(&motg->in_lpm))
		return 0;

	disable_irq(motg->irq);
	/*
	 * Chipidea 45-nm PHY suspend sequence:
	 *
	 * Interrupt Latch Register auto-clear feature is not present
	 * in all PHY versions. Latch register is clear on read type.
	 * Clear latch register to avoid spurious wakeup from
	 * low power mode (LPM).
	 *
	 * PHY comparators are disabled when PHY enters into low power
	 * mode (LPM). Keep PHY comparators ON in LPM only when we expect
	 * VBUS/Id notifications from USB PHY. Otherwise turn off USB
	 * PHY comparators. This save significant amount of power.
	 *
	 * PLL is not turned off when PHY enters into low power mode (LPM).
	 * Disable PLL for maximum power savings.
	 */

	if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY) {
		ulpi_read(phy, 0x14);
		if (pdata->otg_control == OTG_PHY_CONTROL)
			ulpi_write(phy, 0x01, 0x30);
		ulpi_write(phy, 0x08, 0x09);
	}

	/*
	 * PHY may take some time or even fail to enter into low power
	 * mode (LPM). Hence poll for 500 msec and reset the PHY and link
	 * in failure case.
	 */
	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");
		msm_otg_reset(phy);
		enable_irq(motg->irq);
		return -ETIMEDOUT;
	}

	/*
	 * PHY has capability to generate interrupt asynchronously in low
	 * power mode (LPM). This interrupt is level triggered. So USB IRQ
	 * line must be disabled till async interrupt enable bit is cleared
	 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
	 * block data communication from PHY.
	 */
	writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD);

	addr = USB_PHY_CTRL;
	if (motg->phy_number)
		addr = USB_PHY_CTRL2;

	if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
			motg->pdata->otg_control == OTG_PMIC_CONTROL)
		writel(readl(addr) | PHY_RETEN, addr);

	clk_disable_unprepare(motg->pclk);
	clk_disable_unprepare(motg->clk);
	if (!IS_ERR(motg->core_clk))
		clk_disable_unprepare(motg->core_clk);

	if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
			motg->pdata->otg_control == OTG_PMIC_CONTROL) {
		msm_hsusb_ldo_set_mode(motg, 0);
		msm_hsusb_config_vddcx(motg, 0);
	}

	if (device_may_wakeup(phy->dev))
		enable_irq_wake(motg->irq);
	if (bus)
		clear_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);

	atomic_set(&motg->in_lpm, 1);
	enable_irq(motg->irq);

	dev_info(phy->dev, "USB in low power mode\n");

	return 0;
}
コード例 #27
0
ファイル: ehci-msm.c プロジェクト: OpenNoah/u-boot
static void reset_usb_phy(struct msm_ehci_priv *priv)
{
	/* Disable VBUS mimicing in the controller. */
	ulpi_write(&priv->ulpi_vp, (u8 *)ULPI_MISC_A_CLEAR,
		   ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT);
}
コード例 #28
0
ファイル: phy-qcom-usb-hs.c プロジェクト: Lyude/linux
static int qcom_usb_hs_phy_power_on(struct phy *phy)
{
	struct qcom_usb_hs_phy *uphy = phy_get_drvdata(phy);
	struct ulpi *ulpi = uphy->ulpi;
	const struct ulpi_seq *seq;
	int ret, state;

	ret = clk_prepare_enable(uphy->ref_clk);
	if (ret)
		return ret;

	ret = clk_prepare_enable(uphy->sleep_clk);
	if (ret)
		goto err_sleep;

	ret = regulator_set_load(uphy->v1p8, 50000);
	if (ret < 0)
		goto err_1p8;

	ret = regulator_enable(uphy->v1p8);
	if (ret)
		goto err_1p8;

	ret = regulator_set_voltage_triplet(uphy->v3p3, 3050000, 3300000,
					    3300000);
	if (ret)
		goto err_3p3;

	ret = regulator_set_load(uphy->v3p3, 50000);
	if (ret < 0)
		goto err_3p3;

	ret = regulator_enable(uphy->v3p3);
	if (ret)
		goto err_3p3;

	for (seq = uphy->init_seq; seq->addr; seq++) {
		ret = ulpi_write(ulpi, ULPI_EXT_VENDOR_SPECIFIC + seq->addr,
				 seq->val);
		if (ret)
			goto err_ulpi;
	}

	if (uphy->reset) {
		ret = reset_control_reset(uphy->reset);
		if (ret)
			goto err_ulpi;
	}

	if (uphy->vbus_edev) {
		state = extcon_get_state(uphy->vbus_edev, EXTCON_USB);
		/* setup initial state */
		qcom_usb_hs_phy_vbus_notifier(&uphy->vbus_notify, state,
					      uphy->vbus_edev);
		ret = devm_extcon_register_notifier(&ulpi->dev, uphy->vbus_edev,
				EXTCON_USB, &uphy->vbus_notify);
		if (ret)
			goto err_ulpi;
	}

	return 0;
err_ulpi:
	regulator_disable(uphy->v3p3);
err_3p3:
	regulator_disable(uphy->v1p8);
err_1p8:
	clk_disable_unprepare(uphy->sleep_clk);
err_sleep:
	clk_disable_unprepare(uphy->ref_clk);
	return ret;
}
コード例 #29
0
static int msm_otg_suspend(struct msm_otg *dev)
{
	unsigned long timeout;
	int vbus = 0;
	unsigned otgsc;

	disable_irq(dev->irq);
	if (dev->in_lpm)
		goto out;

	/* Don't reset if mini-A cable is connected */
	if (!is_host())
		otg_reset(dev);

	/* In case of fast plug-in and plug-out inside the otg_reset() the
	 * servicing of BSV is missed (in the window of after phy and link
	 * reset). Handle it if any missing bsv is detected */
	if (is_b_sess_vld() && !is_host()) {
		otgsc = readl(USB_OTGSC);
		writel(otgsc, USB_OTGSC);
		pr_info("%s:Process mising BSV\n", __func__);
		msm_otg_start_peripheral(&dev->otg, 1);
		enable_irq(dev->irq);
		return -1;
	}

	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__);
			otg_reset(dev);
			goto out;
		}
		msleep(1);
	}

	writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD);
	clk_disable(dev->pclk);
	if (dev->cclk)
		clk_disable(dev->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);
	}

	dev->in_lpm = 1;

	if (!vbus && dev->pmic_notif_supp)
		dev->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;
}