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