Exemplo n.º 1
0
static int
usbphy_utmi_disable(struct usbphy_softc *sc)
{
	int rv;
	uint32_t val;

	usbphy_utmi_phy_clk(sc, false);

	if (sc->dr_mode == USB_DR_MODE_DEVICE) {
		val = RD4(sc, IF_USB_SUSP_CTRL);
		val &= ~USB_WAKEUP_DEBOUNCE_COUNT(~0);
		val |= USB_WAKE_ON_CNNT_EN_DEV;
		val |= USB_WAKEUP_DEBOUNCE_COUNT(5);
		WR4(sc, IF_USB_SUSP_CTRL, val);
	}

	val = RD4(sc, IF_USB_SUSP_CTRL);
	val |= UTMIP_RESET;
	WR4(sc, IF_USB_SUSP_CTRL, val);

	val = RD4(sc, UTMIP_BAT_CHRG_CFG0);
	val |= UTMIP_PD_CHRG;
	WR4(sc, UTMIP_BAT_CHRG_CFG0, val);

	val = RD4(sc, UTMIP_XCVR_CFG0);
	val |= UTMIP_FORCE_PD_POWERDOWN;
	val |= UTMIP_FORCE_PD2_POWERDOWN;
	val |= UTMIP_FORCE_PDZI_POWERDOWN;
	WR4(sc, UTMIP_XCVR_CFG0, val);

	val = RD4(sc, UTMIP_XCVR_CFG1);
	val |= UTMIP_FORCE_PDDISC_POWERDOWN;
	val |= UTMIP_FORCE_PDCHRP_POWERDOWN;
	val |= UTMIP_FORCE_PDDR_POWERDOWN;
	WR4(sc, UTMIP_XCVR_CFG1, val);

	usbpby_enable_cnt--;
	if (usbpby_enable_cnt <= 0) {
		rv = clk_enable(sc->clk_pads);
		if (rv != 0) {
			device_printf(sc->dev,
			    "Cannot enable 'utmi-pads' clock\n");
			return (rv);
		}
		val =bus_read_4(sc->pads_res, UTMIP_BIAS_CFG0);
		val |= UTMIP_OTGPD;
		val |= UTMIP_BIASPD;
		bus_write_4(sc->pads_res, UTMIP_BIAS_CFG0, val);

		rv = clk_disable(sc->clk_pads);
		if (rv != 0) {
			device_printf(sc->dev,
			    "Cannot disable 'utmi-pads' clock\n");
			return (rv);
		}
	}
	return (0);
}
Exemplo n.º 2
0
static int utmi_phy_power_off(struct tegra_usb_phy *phy)
{
	unsigned long val;
	void __iomem *base = phy->regs;

	DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
	if (!phy->phy_clk_on) {
		DBG("%s(%d) inst:[%d] phy clk is already off\n",
					__func__, __LINE__, phy->inst);
		return 0;
	}

	if (phy->pdata->op_mode == TEGRA_USB_OPMODE_DEVICE) {
		val = readl(base + USB_SUSP_CTRL);
		val &= ~(USB_WAKEUP_DEBOUNCE_COUNT(~0));
		val |= USB_WAKE_ON_CNNT_EN_DEV | USB_WAKEUP_DEBOUNCE_COUNT(5);
		writel(val, base + USB_SUSP_CTRL);

		val = readl(base + UTMIP_BAT_CHRG_CFG0);
		val |= UTMIP_PD_CHRG;
		writel(val, base + UTMIP_BAT_CHRG_CFG0);
	}

	if (!phy->pdata->u_data.host.hot_plug) {
		val = readl(base + UTMIP_XCVR_UHSIC_HSRX_CFG0);
		val |= (UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN |
			 UTMIP_FORCE_PDZI_POWERDOWN);
		writel(val, base + UTMIP_XCVR_UHSIC_HSRX_CFG0);
	}

	val = readl(base + UTMIP_XCVR_CFG1);
	val |= UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN |
		   UTMIP_FORCE_PDDR_POWERDOWN;
	writel(val, base + UTMIP_XCVR_CFG1);

	if (phy->inst != 0) {
		val = readl(base + UTMIP_BIAS_CFG0);
		val |= UTMIP_OTGPD;
		writel(val, base + UTMIP_BIAS_CFG0);
	}

	phy->port_speed = (readl(base + USB_PORTSC) >> 26) &
			USB_PORTSC_PSPD_MASK;

	if (phy->pdata->u_data.host.hot_plug) {
		bool enable_hotplug = true;
		/* if it is OTG port then make sure to enable hot-plug feature
		   only if host adaptor is connected, i.e id is low */
		if (phy->pdata->port_otg) {
			val = readl(base + USB_PHY_VBUS_WAKEUP_ID);
			enable_hotplug = (val & USB_ID_STATUS) ? false : true;
		}
		if (enable_hotplug) {
			val = readl(base + USB_PORTSC);
			val |= USB_PORTSC_WKCN;
			writel(val, base + USB_PORTSC);

			val = readl(base + USB_SUSP_CTRL);
			val |= USB_PHY_CLK_VALID_INT_ENB;
			writel(val, base + USB_SUSP_CTRL);
		} else {
			/* Disable PHY clock valid interrupts while going into suspend*/
			val = readl(base + USB_SUSP_CTRL);
			val &= ~USB_PHY_CLK_VALID_INT_ENB;
			writel(val, base + USB_SUSP_CTRL);
		}
	}

	if (phy->inst == 2) {
		val = readl(base + USB_PORTSC);
		val |= USB_PORTSC_PHCD;
		writel(val, base + USB_PORTSC);
	} else {
		val = readl(base + USB_SUSP_CTRL);
		val |= USB_SUSP_SET;
		writel(val, base + USB_SUSP_CTRL);
		udelay(10);
		val = readl(base + USB_SUSP_CTRL);
		val &= ~USB_SUSP_SET;
		writel(val, base + USB_SUSP_CTRL);
	}

	if (usb_phy_reg_status_wait(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID,
								0, 2500))
		pr_warn("%s: timeout waiting for phy to stabilize\n", __func__);

	utmi_phy_pad_power_off(phy);

	phy->phy_clk_on = false;
	phy->hw_accessible = false;

	DBG("%s(%d) inst:[%d]END\n", __func__, __LINE__, phy->inst);

	return 0;
}