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); }
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__); }