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

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

	spin_lock_irqsave(&pmc_lock, flags);

	if (pmc_data->controller_type == TEGRA_USB_2_0 && usb_base) {
		/* disable PMC master control */
		val = readl(usb_base + UTMIP_PMC_WAKEUP0);
		val &= ~EVENT_INT_ENB;
		writel(val, usb_base + UTMIP_PMC_WAKEUP0);
	}

	val = readl(pmc_base + PMC_SLEEP_CFG);
	val &= ~UTMIP_WAKE_VAL(inst, 0xF);
	val |= UTMIP_WAKE_VAL(inst, WAKE_VAL_NONE);
	writel(val, pmc_base + PMC_SLEEP_CFG);

	/* Disable PMC master mode by clearing MASTER_EN */
	val = readl(pmc_base + PMC_SLEEP_CFG);
	/* WAR for xusb */
	if (pmc_data->controller_type == TEGRA_USB_3_0)
		val |= UTMIP_RCTRL_USE_PMC(inst) | UTMIP_TCTRL_USE_PMC(inst);
	else
		val &= ~(UTMIP_RCTRL_USE_PMC(inst) |
				UTMIP_TCTRL_USE_PMC(inst));
	val &= ~(UTMIP_FSLS_USE_PMC(inst) | UTMIP_MASTER_ENABLE(inst));
	writel(val, pmc_base + PMC_SLEEP_CFG);

	val = readl(pmc_base + PMC_TRIGGERS);
	val &= ~UTMIP_CAP_CFG(inst);
	writel(val, pmc_base + PMC_TRIGGERS);

	/* 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);

	val = readl(pmc_base + PMC_TRIGGERS);
	val |= UTMIP_CLR_WALK_PTR(inst);
	val |= UTMIP_CLR_WAKE_ALARM(inst);
	writel(val, pmc_base + PMC_TRIGGERS);

	if (pmc_data->controller_type == TEGRA_USB_2_0 && enable_sof == 1 &&
		usb_base) {
		val = readl(usb_base + USB_USBCMD);
		val |= USB_USBCMD_RS;
		writel(val, usb_base + USB_USBCMD);
	}
	spin_unlock_irqrestore(&pmc_lock, flags);
}
예제 #2
0
static void usb_phy_power_down_pmc(struct tegra_usb_pmc_data *pmc_data)
{
	unsigned long val;

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

	spin_lock_irqsave(&pmc_lock, flags);

	/* power down all 3 UTMIP interfaces */
	val = readl(pmc_base + PMC_UTMIP_MASTER_CONFIG);
	val |= UTMIP_PWR(0) | UTMIP_PWR(1) | UTMIP_PWR(2);
	writel(val, pmc_base + PMC_UTMIP_MASTER_CONFIG);

	/* turn on pad detectors */
	writel(PMC_POWER_DOWN_MASK, pmc_base + PMC_USB_AO);

	/* setup sleep walk fl all 3 usb controllers */
	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(0));
	writel(val, pmc_base + PMC_SLEEPWALK_REG(1));
	writel(val, pmc_base + PMC_SLEEPWALK_REG(2));

	/* enable pull downs on HSIC PMC */
	val = UHSIC_STROBE_RPD_A | UHSIC_DATA_RPD_A | UHSIC_STROBE_RPD_B |
		UHSIC_DATA_RPD_B | UHSIC_STROBE_RPD_C | UHSIC_DATA_RPD_C |
		UHSIC_STROBE_RPD_D | UHSIC_DATA_RPD_D;
	writel(val, pmc_base + PMC_SLEEPWALK_UHSIC);

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

	spin_unlock_irqrestore(&pmc_lock, flags);
}
예제 #3
0
static void utmip_powerup_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);

	/* Disable PMC master mode by clearing MASTER_EN */
	val = readl(pmc_base + PMC_SLEEP_CFG);
	/* WAR for xusb */
	if (pmc_data->controller_type == TEGRA_USB_3_0)
		val |= UTMIP_RCTRL_USE_PMC(inst) | UTMIP_TCTRL_USE_PMC(inst);
	else
		val &= ~(UTMIP_RCTRL_USE_PMC(inst) |
				UTMIP_TCTRL_USE_PMC(inst));
	val &= ~(UTMIP_FSLS_USE_PMC(inst) | UTMIP_MASTER_ENABLE(inst));
	writel(val, pmc_base + PMC_SLEEP_CFG);

	spin_unlock_irqrestore(&pmc_lock, flags);
	mdelay(1);
}
예제 #4
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);
}
static void utmip_phy_disable_pmc_bus_ctrl(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);

    val = readl(pmc_base + PMC_SLEEP_CFG);
    val &= ~UTMIP_WAKE_VAL(inst, 0xF);
    val |= UTMIP_WAKE_VAL(inst, WAKE_VAL_NONE);
    writel(val, pmc_base + PMC_SLEEP_CFG);

    /* Disable PMC master mode by clearing MASTER_EN */
    val = readl(pmc_base + PMC_SLEEP_CFG);
    val &= ~(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);

    val = readl(pmc_base + PMC_TRIGGERS);
    val &= ~UTMIP_CAP_CFG(inst);
    writel(val, pmc_base + PMC_TRIGGERS);

    /* 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);

    val = readl(pmc_base + PMC_TRIGGERS);
    val |= UTMIP_CLR_WALK_PTR(inst);
    val |= UTMIP_CLR_WAKE_ALARM(inst);
    writel(val, pmc_base + PMC_TRIGGERS);

    spin_unlock_irqrestore(&pmc_lock, flags);
}
예제 #6
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);
}