static int utmi_phy_power_on(struct tegra_usb_phy *phy)
{
	unsigned long val;
	void __iomem *base = phy->regs;
	struct tegra_utmi_config *config = &phy->pdata->u_cfg.utmi;
	DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
	if (phy->phy_clk_on) {
		DBG("%s(%d) inst:[%d] phy clk is already on\n",
					__func__, __LINE__, phy->inst);
		return 0;
	}

	val = readl(base + USB_SUSP_CTRL);
	val |= UTMIP_RESET;
	writel(val, base + USB_SUSP_CTRL);

	val = readl(base + UTMIP_TX_CFG0);
	val |= UTMIP_FS_PREABMLE_J;
	writel(val, base + UTMIP_TX_CFG0);

	val = readl(base + UTMIP_HSRX_CFG0);
	val &= ~(UTMIP_IDLE_WAIT(~0) | UTMIP_ELASTIC_LIMIT(~0));
	val |= UTMIP_IDLE_WAIT(config->idle_wait_delay);
	val |= UTMIP_ELASTIC_LIMIT(config->elastic_limit);
	writel(val, base + UTMIP_HSRX_CFG0);

	val = readl(base + UTMIP_HSRX_CFG1);
	val &= ~(UTMIP_HS_SYNC_START_DLY(~0));
	val |= UTMIP_HS_SYNC_START_DLY(config->hssync_start_delay);
	writel(val, base + UTMIP_HSRX_CFG1);

	val = readl(base + UTMIP_DEBOUNCE_CFG0);
	val &= ~UTMIP_BIAS_DEBOUNCE_A(~0);
	val |= UTMIP_BIAS_DEBOUNCE_A(phy->freq->debounce);
	writel(val, base + UTMIP_DEBOUNCE_CFG0);

	val = readl(base + UTMIP_MISC_CFG0);
	val &= ~UTMIP_SUSPEND_EXIT_ON_EDGE;
	writel(val, base + UTMIP_MISC_CFG0);

	val = readl(base + UTMIP_MISC_CFG1);
	val &= ~(UTMIP_PLL_ACTIVE_DLY_COUNT(~0) | UTMIP_PLLU_STABLE_COUNT(~0));
	val |= UTMIP_PLL_ACTIVE_DLY_COUNT(phy->freq->active_delay) |
		UTMIP_PLLU_STABLE_COUNT(phy->freq->stable_count);
	writel(val, base + UTMIP_MISC_CFG1);

	val = readl(base + UTMIP_PLL_CFG1);
	val &= ~(UTMIP_XTAL_FREQ_COUNT(~0) | UTMIP_PLLU_ENABLE_DLY_COUNT(~0));
	val |= UTMIP_XTAL_FREQ_COUNT(phy->freq->xtal_freq_count) |
		UTMIP_PLLU_ENABLE_DLY_COUNT(phy->freq->enable_delay);
	writel(val, base + UTMIP_PLL_CFG1);

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

		val = readl(base + UTMIP_BAT_CHRG_CFG0);
		val &= ~UTMIP_PD_CHRG;
		writel(val, base + UTMIP_BAT_CHRG_CFG0);
	} else {
		val = readl(base + UTMIP_BAT_CHRG_CFG0);
		val |= UTMIP_PD_CHRG;
		writel(val, base + UTMIP_BAT_CHRG_CFG0);
	}

	utmi_phy_pad_power_on(phy);

	val = readl(base + UTMIP_XCVR_UHSIC_HSRX_CFG0);
	val &= ~(UTMIP_XCVR_LSBIAS_SEL | UTMIP_FORCE_PD_POWERDOWN |
		 UTMIP_FORCE_PD2_POWERDOWN | UTMIP_FORCE_PDZI_POWERDOWN |
		 UTMIP_XCVR_SETUP(~0) | UTMIP_XCVR_LSFSLEW(~0) |
		 UTMIP_XCVR_LSRSLEW(~0) | UTMIP_XCVR_HSSLEW_MSB(~0));
	val |= UTMIP_XCVR_SETUP(phy->utmi_xcvr_setup);
	val |= UTMIP_XCVR_SETUP_MSB(XCVR_SETUP_MSB_CALIB(phy->utmi_xcvr_setup));
	val |= UTMIP_XCVR_LSFSLEW(config->xcvr_lsfslew);
	val |= UTMIP_XCVR_LSRSLEW(config->xcvr_lsrslew);

	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 | UTMIP_XCVR_TERM_RANGE_ADJ(~0));
	val |= UTMIP_XCVR_TERM_RANGE_ADJ(config->term_range_adj);
	writel(val, base + UTMIP_XCVR_CFG1);


	val = readl(base + UTMIP_BIAS_CFG1);
	val &= ~(UTMIP_BIAS_PDTRK_COUNT(~0));
	val |= UTMIP_BIAS_PDTRK_COUNT(phy->freq->pdtrk_count);
	writel(val, base + UTMIP_BIAS_CFG1);

	val = readl(base + UTMIP_SPARE_CFG0);
	val &= ~FUSE_SETUP_SEL;
	writel(val, base + UTMIP_SPARE_CFG0);

	val = readl(base + USB_SUSP_CTRL);
	val |= UTMIP_PHY_ENABLE;
	writel(val, base + USB_SUSP_CTRL);

	val = readl(base + USB_SUSP_CTRL);
	val &= ~UTMIP_RESET;
	writel(val, base + USB_SUSP_CTRL);

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

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

	if (phy->inst == 2) {
		val = readl(base + USB_PORTSC);
		val &= ~(USB_PORTSC_PTS(~0));
		writel(val, base + USB_PORTSC);
	}

	phy->phy_clk_on = true;
	phy->hw_accessible = true;

	return 0;
}
Exemple #2
0
static int
usbphy_utmi_enable(struct usbphy_softc *sc)
{
	int rv;
	uint32_t val;

	/* Reset phy */
	val = RD4(sc, IF_USB_SUSP_CTRL);
	val |= UTMIP_RESET;
	WR4(sc, IF_USB_SUSP_CTRL, val);


	val = RD4(sc, UTMIP_TX_CFG0);
	val |= UTMIP_FS_PREAMBLE_J;
	WR4(sc, UTMIP_TX_CFG0, val);

	val = RD4(sc, UTMIP_HSRX_CFG0);
	val &= ~UTMIP_IDLE_WAIT(~0);
	val &= ~UTMIP_ELASTIC_LIMIT(~0);
	val |= UTMIP_IDLE_WAIT(sc->idle_wait_delay);
	val |= UTMIP_ELASTIC_LIMIT(sc->elastic_limit);
	WR4(sc, UTMIP_HSRX_CFG0, val);

	val = RD4(sc, UTMIP_HSRX_CFG1);
	val &= ~UTMIP_HS_SYNC_START_DLY(~0);
	val |= UTMIP_HS_SYNC_START_DLY(sc->hssync_start_delay);
	WR4(sc, UTMIP_HSRX_CFG1, val);

	val = RD4(sc, UTMIP_DEBOUNCE_CFG0);
	val &= ~UTMIP_BIAS_DEBOUNCE_A(~0);
	val |= UTMIP_BIAS_DEBOUNCE_A(0x7530);  /* For 12MHz */
	WR4(sc, UTMIP_DEBOUNCE_CFG0, val);

	val = RD4(sc, UTMIP_MISC_CFG0);
	val &= ~UTMIP_SUSPEND_EXIT_ON_EDGE;
	WR4(sc, UTMIP_MISC_CFG0, val);

	if (sc->dr_mode == USB_DR_MODE_DEVICE) {
		val = RD4(sc,IF_USB_SUSP_CTRL);
		val &= ~USB_WAKE_ON_CNNT_EN_DEV;
		val &= ~USB_WAKE_ON_DISCON_EN_DEV;
		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);
	} else {
		val = RD4(sc, UTMIP_BAT_CHRG_CFG0);
		val |= UTMIP_PD_CHRG;
		WR4(sc, UTMIP_BAT_CHRG_CFG0, val);
	}

	usbpby_enable_cnt++;
	if (usbpby_enable_cnt == 1) {
		rv = hwreset_deassert(sc->reset_pads);
		if (rv != 0) {
			device_printf(sc->dev,
			     "Cannot unreset 'utmi-pads' reset\n");
			return (rv);
		}
		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;
		val &= ~UTMIP_HSSQUELCH_LEVEL(~0);
		val &= ~UTMIP_HSDISCON_LEVEL(~0);
		val &= ~UTMIP_HSDISCON_LEVEL_MSB(~0);
		val |= UTMIP_HSSQUELCH_LEVEL(sc->hssquelch_level);
		val |= UTMIP_HSDISCON_LEVEL(sc->hsdiscon_level);
		val |= UTMIP_HSDISCON_LEVEL_MSB(sc->hsdiscon_level);
		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);
		}
	}

	val = RD4(sc, UTMIP_XCVR_CFG0);
	val &= ~UTMIP_FORCE_PD_POWERDOWN;
	val &= ~UTMIP_FORCE_PD2_POWERDOWN ;
	val &= ~UTMIP_FORCE_PDZI_POWERDOWN;
	val &= ~UTMIP_XCVR_LSBIAS_SEL;
	val &= ~UTMIP_XCVR_LSFSLEW(~0);
	val &= ~UTMIP_XCVR_LSRSLEW(~0);
	val &= ~UTMIP_XCVR_HSSLEW(~0);
	val &= ~UTMIP_XCVR_HSSLEW_MSB(~0);
	val |= UTMIP_XCVR_LSFSLEW(sc->xcvr_lsfslew);
	val |= UTMIP_XCVR_LSRSLEW(sc->xcvr_lsrslew);
	val |= UTMIP_XCVR_HSSLEW(sc->xcvr_hsslew);
	val |= UTMIP_XCVR_HSSLEW_MSB(sc->xcvr_hsslew);
	if (!sc->xcvr_setup_use_fuses) {
		val &= ~UTMIP_XCVR_SETUP(~0);
		val &= ~UTMIP_XCVR_SETUP_MSB(~0);
		val |= UTMIP_XCVR_SETUP(sc->xcvr_setup);
		val |= UTMIP_XCVR_SETUP_MSB(sc->xcvr_setup);
	}
	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;
	val &= ~UTMIP_XCVR_TERM_RANGE_ADJ(~0);
	val |= UTMIP_XCVR_TERM_RANGE_ADJ(sc->term_range_adj);
	WR4(sc, UTMIP_XCVR_CFG1, val);


	val = RD4(sc, UTMIP_BIAS_CFG1);
	val &= ~UTMIP_BIAS_PDTRK_COUNT(~0);
	val |= UTMIP_BIAS_PDTRK_COUNT(0x5);
	WR4(sc, UTMIP_BIAS_CFG1, val);

	val = RD4(sc, UTMIP_SPARE_CFG0);
	if (sc->xcvr_setup_use_fuses)
		val |= FUSE_SETUP_SEL;
	else
		val &= ~FUSE_SETUP_SEL;
	WR4(sc, UTMIP_SPARE_CFG0, val);

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

	val = RD4(sc, IF_USB_SUSP_CTRL);
	val &= ~UTMIP_RESET;
	WR4(sc, IF_USB_SUSP_CTRL, val);

	usbphy_utmi_phy_clk(sc, true);

	val = RD4(sc, CTRL_USB_USBMODE);
	val &= ~USB_USBMODE_MASK;
	if (sc->dr_mode == USB_DR_MODE_HOST)
		val |= USB_USBMODE_HOST;
	else
		val |= USB_USBMODE_DEVICE;
	WR4(sc, CTRL_USB_USBMODE, val);

	val = RD4(sc, CTRL_USB_HOSTPC1_DEVLC);
	val &= ~USB_HOSTPC1_DEVLC_PTS(~0);
	val |= USB_HOSTPC1_DEVLC_PTS(0);
	WR4(sc, CTRL_USB_HOSTPC1_DEVLC, val);

	return (0);
}