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