static void uhsic_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);

	/* turn off pad detectors for HSIC*/
	val = readl(pmc_base + PMC_USB_AO);
	val |= (HSIC_RESERVED(inst) | STROBE_VAL_PD(inst) | DATA_VAL_PD(inst));
	writel(val, pmc_base + PMC_USB_AO);

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

	/* Turn over pad configuration to PMC */
	val = readl(pmc_base + PMC_UHSIC_SLEEP_CFG(inst));
	val &= ~UHSIC_WAKE_VAL(inst, ~0);
	val |= UHSIC_WAKE_VAL(inst, WAKE_VAL_NONE) | UHSIC_MASTER_ENABLE(inst);
	writel(val, pmc_base + PMC_UHSIC_SLEEP_CFG(inst));

	spin_unlock_irqrestore(&pmc_lock, flags);
}
Exemple #2
0
static void uhsic_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_UHSIC_SLEEP_CFG(inst));
	val &= ~UHSIC_WAKE_VAL(inst, WAKE_VAL_ANY);
	val |= UHSIC_WAKE_VAL(inst, WAKE_VAL_NONE);
	writel(val, pmc_base + PMC_UHSIC_SLEEP_CFG(inst));

	/* Disable PMC master mode by clearing MASTER_EN */
	val = readl(pmc_base + PMC_UHSIC_SLEEP_CFG(inst));
	val &= ~(UHSIC_MASTER_ENABLE(inst));
	writel(val, pmc_base + PMC_UHSIC_SLEEP_CFG(inst));

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

	val = readl(pmc_base + PMC_UHSIC_TRIGGERS(inst));
	val |= (UHSIC_CLR_WALK_PTR(inst) | UHSIC_CLR_WAKE_ALARM(inst));
	writel(val, pmc_base + PMC_UHSIC_TRIGGERS(inst));

	spin_unlock_irqrestore(&pmc_lock, flags);
}
static void uhsic_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_UHSIC_SLEEP_CFG(inst));
	val &= ~UHSIC_WAKE_VAL(inst, WAKE_VAL_ANY);
	val |= UHSIC_WAKE_VAL(inst, WAKE_VAL_NONE);
	writel(val, pmc_base + PMC_UHSIC_SLEEP_CFG(inst));

	/* Disable PMC master mode by clearing MASTER_EN */
	val = readl(pmc_base + PMC_UHSIC_SLEEP_CFG(inst));
	val &= ~(UHSIC_MASTER_ENABLE(inst));
	writel(val, pmc_base + PMC_UHSIC_SLEEP_CFG(inst));

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

	val = readl(pmc_base + PMC_UHSIC_TRIGGERS(inst));
	val |= (UHSIC_CLR_WALK_PTR(inst) | UHSIC_CLR_WAKE_ALARM(inst));
	writel(val, pmc_base + PMC_UHSIC_TRIGGERS(inst));

	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);
}
static void uhsic_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);

	/* turn on pad detectors for HSIC*/
	val = readl(pmc_base + PMC_USB_AO);
	val &= ~(HSIC_RESERVED(inst) | STROBE_VAL_PD(inst) | DATA_VAL_PD(inst));
	writel(val, pmc_base + PMC_USB_AO);

	/* Disable PMC master mode by clearing MASTER_EN */
	val = readl(pmc_base + PMC_UHSIC_SLEEP_CFG(inst));
	val &= ~(UHSIC_MASTER_ENABLE(inst));
	writel(val, pmc_base + PMC_UHSIC_SLEEP_CFG(inst));

	spin_unlock_irqrestore(&pmc_lock, flags);
	mdelay(1);
}
static void uhsic_setup_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);

	/*Set PMC MASTER bits to do the following
	* a. Take over the hsic 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_UHSIC_SLEEP_CFG(inst));
	val &= ~UHSIC_MASTER_ENABLE(inst);
	writel(val, pmc_base + PMC_UHSIC_SLEEP_CFG(inst));

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

	/* config debouncer */
	val = readl(pmc_base + PMC_USB_DEBOUNCE);
	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_UHSIC_FAKE(inst));
	val &= ~UHSIC_FAKE_STROBE_VAL(inst);
	val &= ~UHSIC_FAKE_DATA_VAL(inst);
	writel(val, pmc_base + PMC_UHSIC_FAKE(inst));

	/* Clear walk enable */
	val = readl(pmc_base + PMC_UHSIC_SLEEPWALK_CFG(inst));
	val &= ~UHSIC_LINEVAL_WALK_EN(inst);
	writel(val, pmc_base + PMC_UHSIC_SLEEPWALK_CFG(inst));

	/* Make sure wake value for line is none */
	val = readl(pmc_base + PMC_UHSIC_SLEEP_CFG(inst));
	val &= ~UHSIC_WAKE_VAL(inst, WAKE_VAL_ANY);
	val |= UHSIC_WAKE_VAL(inst, WAKE_VAL_NONE);
	writel(val, pmc_base + PMC_UHSIC_SLEEP_CFG(inst));

	/* turn on pad detectors */
	val = readl(pmc_base + PMC_USB_AO);
	val &= ~(STROBE_VAL_PD(inst) | DATA_VAL_PD(inst));
	writel(val, pmc_base + PMC_USB_AO);

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

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

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

	val &= ~UHSIC_DATA_RPU_A;
	val |=  UHSIC_DATA_RPD_A;
	val &= ~UHSIC_STROBE_RPD_A;
	val |=  UHSIC_STROBE_RPU_A;

	val &= ~UHSIC_DATA_RPD_B;
	val |=  UHSIC_DATA_RPU_B;
	val &= ~UHSIC_STROBE_RPU_B;
	val |=  UHSIC_STROBE_RPD_B;

	val &= ~UHSIC_DATA_RPD_C;
	val |=  UHSIC_DATA_RPU_C;
	val &= ~UHSIC_STROBE_RPU_C;
	val |=  UHSIC_STROBE_RPD_C;

	val &= ~UHSIC_DATA_RPD_D;
	val |=  UHSIC_DATA_RPU_D;
	val &= ~UHSIC_STROBE_RPU_D;
	val |=  UHSIC_STROBE_RPD_D;
	writel(val, pmc_base + PMC_SLEEPWALK_UHSIC(inst));

	/* Setting Wake event*/
	val = readl(pmc_base + PMC_UHSIC_SLEEP_CFG(inst));
	val &= ~UHSIC_WAKE_VAL(inst, WAKE_VAL_ANY);
	val |= UHSIC_WAKE_VAL(inst, WAKE_VAL_SD10);
	writel(val, pmc_base + PMC_UHSIC_SLEEP_CFG(inst));

	/* Clear the walk pointers and wake alarm */
	val = readl(pmc_base + PMC_UHSIC_TRIGGERS(inst));
	val |= UHSIC_CLR_WAKE_ALARM(inst) | UHSIC_CLR_WALK_PTR(inst);
	writel(val, pmc_base + PMC_UHSIC_TRIGGERS(inst));

	/* Turn over pad configuration to PMC  for line wake events*/
	val = readl(pmc_base + PMC_UHSIC_SLEEP_CFG(inst));
	val |= UHSIC_MASTER_ENABLE(inst);
	writel(val, pmc_base + PMC_UHSIC_SLEEP_CFG(inst));

	spin_unlock_irqrestore(&pmc_lock, flags);
	DBG("%s:PMC enabled for HSIC remote wakeup\n", __func__);
}