예제 #1
0
static void utmip_powerdown_pmc_wake_detect(struct tegra_usb_pmc_data *pmc_data)
{
	unsigned long val;
	unsigned  int inst = pmc_data->instance;

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

	spin_lock_irqsave(&pmc_lock, flags);

	/* power down UTMIP interfaces */
	val = readl(pmc_base + PMC_UTMIP_MASTER_CONFIG);
	val |= UTMIP_PWR(inst);
	writel(val, pmc_base + PMC_UTMIP_MASTER_CONFIG);

	/* setup sleep walk usb controller */
	val = UTMIP_USBOP_RPD_A | UTMIP_USBON_RPD_A | UTMIP_HIGHZ_A |
		UTMIP_USBOP_RPD_B | UTMIP_USBON_RPD_B | UTMIP_HIGHZ_B |
		UTMIP_USBOP_RPD_C | UTMIP_USBON_RPD_C | UTMIP_HIGHZ_C |
		UTMIP_USBOP_RPD_D | UTMIP_USBON_RPD_D | UTMIP_HIGHZ_D;
	writel(val, pmc_base + PMC_SLEEPWALK_REG(inst));

	/* Program thermally encoded RCTRL_VAL, TCTRL_VAL into PMC space */
	if (pmc_data->utmip_tctrl_val | pmc_data->utmip_rctrl_val) {
		val = readl(pmc_base + PMC_UTMIP_TERM_PAD_CFG);
		val = PMC_TCTRL_VAL(pmc_data->utmip_tctrl_val) |
			PMC_RCTRL_VAL(pmc_data->utmip_rctrl_val);
		writel(val, pmc_base + PMC_UTMIP_TERM_PAD_CFG);
	}

	/* Turn over pad configuration to PMC */
	val = readl(pmc_base + PMC_SLEEP_CFG);
	val &= ~UTMIP_WAKE_VAL(inst, ~0);
	val |= UTMIP_WAKE_VAL(inst, WAKE_VAL_NONE) |
		UTMIP_RCTRL_USE_PMC(inst) | UTMIP_TCTRL_USE_PMC(inst) |
		UTMIP_FSLS_USE_PMC(inst) | UTMIP_MASTER_ENABLE(inst);
	writel(val, pmc_base + PMC_SLEEP_CFG);

	spin_unlock_irqrestore(&pmc_lock, flags);
}
예제 #2
0
static void utmip_setup_pmc_wake_detect(struct tegra_usb_pmc_data *pmc_data)
{
	unsigned long val, pmc_pad_cfg_val;
	unsigned  int inst = pmc_data->instance;

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

	spin_lock_irqsave(&pmc_lock, flags);

	/*Set PMC MASTER bits to do the following
	* a. Take over the UTMI drivers
	* b. set up such that it will take over resume
	*	 if remote wakeup is detected
	* Prepare PMC to take over suspend-wake detect-drive resume until USB
	* controller ready
	*/

	/* disable master enable in PMC */
	val = readl(pmc_base + PMC_SLEEP_CFG);
	val &= ~UTMIP_MASTER_ENABLE(inst);
	writel(val, pmc_base + PMC_SLEEP_CFG);

	/* UTMIP_PWR_PX=1 for power savings mode */
	val = readl(pmc_base + PMC_UTMIP_MASTER_CONFIG);
	val |= UTMIP_PWR(inst);
	writel(val, pmc_base + PMC_UTMIP_MASTER_CONFIG);

	/* config debouncer */
	val = readl(pmc_base + PMC_USB_DEBOUNCE);
	val &= ~UTMIP_LINE_DEB_CNT(~0);
	val |= UTMIP_LINE_DEB_CNT(1);
	val |= PMC_USB_DEBOUNCE_VAL(2);
	writel(val, pmc_base + PMC_USB_DEBOUNCE);

	/* Make sure nothing is happening on the line with respect to PMC */
	val = readl(pmc_base + PMC_UTMIP_FAKE);
	val &= ~USBOP_VAL(inst);
	val &= ~USBON_VAL(inst);
	writel(val, pmc_base + PMC_UTMIP_FAKE);

	/* Make sure wake value for line is none */
	val = readl(pmc_base + PMC_SLEEPWALK_CFG);
	val &= ~UTMIP_LINEVAL_WALK_EN(inst);
	writel(val, pmc_base + PMC_SLEEPWALK_CFG);
	val = readl(pmc_base + PMC_SLEEP_CFG);
	val &= ~UTMIP_WAKE_VAL(inst, ~0);
	val |= UTMIP_WAKE_VAL(inst, WAKE_VAL_NONE);
	writel(val, pmc_base + PMC_SLEEP_CFG);

	/* turn off pad detectors */
	val = readl(pmc_base + PMC_USB_AO);
	val |= (USBOP_VAL_PD(inst) | USBON_VAL_PD(inst));
	writel(val, pmc_base + PMC_USB_AO);

	/* Remove fake values and make synchronizers work a bit */
	val = readl(pmc_base + PMC_UTMIP_FAKE);
	val &= ~USBOP_VAL(inst);
	val &= ~USBON_VAL(inst);
	writel(val, pmc_base + PMC_UTMIP_FAKE);

	/* Enable which type of event can trigger a walk,
	* in this case usb_line_wake */
	val = readl(pmc_base + PMC_SLEEPWALK_CFG);
	val |= UTMIP_LINEVAL_WALK_EN(inst);
	writel(val, pmc_base + PMC_SLEEPWALK_CFG);

	/* Capture FS/LS pad configurations */
	pmc_pad_cfg_val = readl(pmc_base + PMC_PAD_CFG);
	val = readl(pmc_base + PMC_TRIGGERS);
	val |= UTMIP_CAP_CFG(inst);
	writel(val, pmc_base + PMC_TRIGGERS);
	udelay(1);
	pmc_pad_cfg_val = readl(pmc_base + PMC_PAD_CFG);

	/* BIAS MASTER_ENABLE=0 */
	val = readl(pmc_base + PMC_UTMIP_BIAS_MASTER_CNTRL);
	val &= ~BIAS_MASTER_PROG_VAL;
	writel(val, pmc_base + PMC_UTMIP_BIAS_MASTER_CNTRL);

	/* program walk sequence for remote or hotplug wakeup */
	if ((pmc_data->port_speed < USB_PMC_PORT_SPEED_UNKNOWN) ||
		(pmc_data->port_speed == USB_PMC_PORT_SPEED_SUPER)) {
		/* program walk sequence, maintain a J, followed by a driven K
		* to signal a resume once an wake event is detected */
		val = readl(pmc_base + PMC_SLEEPWALK_REG(inst));
		val &= ~UTMIP_AP_A;
		val |= UTMIP_USBOP_RPD_A | UTMIP_USBON_RPD_A | UTMIP_AN_A |
					UTMIP_HIGHZ_A |
			UTMIP_USBOP_RPD_B | UTMIP_USBON_RPD_B | UTMIP_AP_B |
					UTMIP_AN_B |
			UTMIP_USBOP_RPD_C | UTMIP_USBON_RPD_C | UTMIP_AP_C |
					UTMIP_AN_C |
			UTMIP_USBOP_RPD_D | UTMIP_USBON_RPD_D | UTMIP_AP_D |
					UTMIP_AN_D;
		writel(val, pmc_base + PMC_SLEEPWALK_REG(inst));

		if (pmc_data->port_speed == USB_PMC_PORT_SPEED_LOW) {
			val = readl(pmc_base + PMC_SLEEPWALK_REG(inst));
			val &= ~(UTMIP_AN_B | UTMIP_HIGHZ_B | UTMIP_AN_C |
				UTMIP_HIGHZ_C | UTMIP_AN_D | UTMIP_HIGHZ_D);
			writel(val, pmc_base + PMC_SLEEPWALK_REG(inst));
		} else {
			val = readl(pmc_base + PMC_SLEEPWALK_REG(inst));
			val &= ~(UTMIP_AP_B | UTMIP_HIGHZ_B | UTMIP_AP_C |
				UTMIP_HIGHZ_C | UTMIP_AP_D | UTMIP_HIGHZ_D |
				UTMIP_AN_A);
				val |= UTMIP_AP_A;
			writel(val, pmc_base + PMC_SLEEPWALK_REG(inst));
		}
	} else {
		/* program walk sequence, pull down both dp and dn lines,
		* tristate lines once an hotplug-in wake event is detected */
		val = readl(pmc_base + PMC_SLEEPWALK_REG(inst));
		val |= UTMIP_USBOP_RPD_A | UTMIP_USBON_RPD_A | UTMIP_HIGHZ_A;
		val &= ~UTMIP_AP_A;
		val &= ~UTMIP_AN_A;
		val |= UTMIP_USBOP_RPD_B | UTMIP_USBON_RPD_B | UTMIP_HIGHZ_B;
		val &= ~UTMIP_AP_B;
		val &= ~UTMIP_AN_B;
		val |= UTMIP_USBOP_RPD_C | UTMIP_USBON_RPD_C | UTMIP_HIGHZ_C;
		val &= ~UTMIP_AP_C;
		val &= ~UTMIP_AN_C;
		val |= UTMIP_USBOP_RPD_D | UTMIP_USBON_RPD_D | UTMIP_HIGHZ_D;
		val &= ~UTMIP_AP_D;
		val &= ~UTMIP_AN_D;
		writel(val, pmc_base + PMC_SLEEPWALK_REG(inst));
	}
	/* turn on pad detectors */
	val = readl(pmc_base + PMC_USB_AO);
	val &= ~(USBOP_VAL_PD(inst) | USBON_VAL_PD(inst));
	writel(val, pmc_base + PMC_USB_AO);

	spin_unlock_irqrestore(&pmc_lock, flags);

	/* Add small delay before usb detectors provide stable line values */
	mdelay(1);

	spin_lock_irqsave(&pmc_lock, flags);

	/* Program thermally encoded RCTRL_VAL, TCTRL_VAL into PMC space */
	if (pmc_data->utmip_tctrl_val | pmc_data->utmip_rctrl_val) {
		val = readl(pmc_base + PMC_UTMIP_TERM_PAD_CFG);
		val = PMC_TCTRL_VAL(pmc_data->utmip_tctrl_val) |
			PMC_RCTRL_VAL(pmc_data->utmip_rctrl_val);
		writel(val, pmc_base + PMC_UTMIP_TERM_PAD_CFG);
	}

	/* Turn over pad configuration to PMC  for line wake events*/
	val = readl(pmc_base + PMC_SLEEP_CFG);
	val &= ~UTMIP_WAKE_VAL(inst, ~0);
	val |= UTMIP_WAKE_VAL(inst, WAKE_VAL_ANY);
	val |= UTMIP_RCTRL_USE_PMC(inst) | UTMIP_TCTRL_USE_PMC(inst);
	val |= UTMIP_MASTER_ENABLE(inst) | UTMIP_FSLS_USE_PMC(inst);
	writel(val, pmc_base + PMC_SLEEP_CFG);

	spin_unlock_irqrestore(&pmc_lock, flags);
}
예제 #3
0
int utmi_phy_set_snps_trking_data(void)
{
	void __iomem *base = IO_ADDRESS(TEGRA_USB_BASE);
	u32 val;
	struct clk *utmi_pad_clk;

	utmi_pad_clk = clk_get_sys("utmip-pad", NULL);
	if (IS_ERR(utmi_pad_clk)) {
		pr_err("%s: can't get utmip pad clock\n", __func__);
		return PTR_ERR(utmi_pad_clk);
	}

	if (!pmc_base)
		pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);

	clk_enable(utmi_pad_clk);
	spin_lock_irqsave(&pmc_lock, flags);
	/* Bias pad MASTER_ENABLE=1 */
	val = readl(pmc_base + PMC_UTMIP_BIAS_MASTER_CNTRL);
	val |= BIAS_MASTER_PROG_VAL;
	writel(val, pmc_base + PMC_UTMIP_BIAS_MASTER_CNTRL);

	/* Setting the tracking length time */
	val = readl(base + UTMIP_BIAS_CFG1);
	val &= ~UTMIP_BIAS_PDTRK_COUNT(~0);
	val |= UTMIP_BIAS_PDTRK_COUNT(5);
	writel(val, base + UTMIP_BIAS_CFG1);

	/* Bias PDTRK is Shared and MUST be done from USB1 ONLY, PD_TRK=0 */
	val = readl(base + UTMIP_BIAS_CFG1);
	val &= ~UTMIP_BIAS_PDTRK_POWERDOWN;
	writel(val, base + UTMIP_BIAS_CFG1);

	val = readl(base + UTMIP_BIAS_CFG1);
	val |= UTMIP_BIAS_PDTRK_POWERUP;
	writel(val, base + UTMIP_BIAS_CFG1);

	/* Wait for 25usec */
	udelay(25);

	/* Bias pad MASTER_ENABLE=0 */
	val = readl(pmc_base + PMC_UTMIP_BIAS_MASTER_CNTRL);
	val &= ~BIAS_MASTER_PROG_VAL;
	writel(val, pmc_base + PMC_UTMIP_BIAS_MASTER_CNTRL);

	/* Wait for 1usec */
	udelay(1);

	/* Bias pad MASTER_ENABLE=1 */
	val = readl(pmc_base + PMC_UTMIP_BIAS_MASTER_CNTRL);
	val |= BIAS_MASTER_PROG_VAL;
	writel(val, pmc_base + PMC_UTMIP_BIAS_MASTER_CNTRL);

	/* Read RCTRL and TCTRL from UTMIP space */
	val = readl(base + UTMIP_BIAS_STS0);
	utmip_rctrl_val = 0xf + ffz(UTMIP_RCTRL_VAL(val));
	utmip_tctrl_val = 0xf + ffz(UTMIP_TCTRL_VAL(val));

	/* PD_TRK=1 */
	val = readl(base + UTMIP_BIAS_CFG1);
	val |= UTMIP_BIAS_PDTRK_POWERDOWN;
	writel(val, base + UTMIP_BIAS_CFG1);

	/* Program thermally encoded RCTRL_VAL, TCTRL_VAL into PMC space */
	val = readl(pmc_base + PMC_UTMIP_TERM_PAD_CFG);
	val = PMC_TCTRL_VAL(utmip_tctrl_val) |
		PMC_RCTRL_VAL(utmip_rctrl_val);
	writel(val, pmc_base + PMC_UTMIP_TERM_PAD_CFG);
	spin_unlock_irqrestore(&pmc_lock, flags);
	clk_disable(utmi_pad_clk);
	clk_put(utmi_pad_clk);

	return 0;
}