static int omap_usb_dpll_lock(struct omap_usb *phy) { u32 val; unsigned long rate; enum sys_clk_rate clk_index; rate = clk_get_rate(phy->sys_clk); clk_index = __get_sys_clk_index(rate); if (clk_index == CLK_RATE_UNDEFINED) { pr_err("dpll cannot be locked for sys clk freq:%luHz\n", rate); return -EINVAL; } val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1); val &= ~PLL_REGN_MASK; val |= omap_usb3_dpll_params[clk_index].n << PLL_REGN_SHIFT; omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val); val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); val &= ~PLL_SELFREQDCO_MASK; val |= omap_usb3_dpll_params[clk_index].freq << PLL_SELFREQDCO_SHIFT; omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val); val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1); val &= ~PLL_REGM_MASK; val |= omap_usb3_dpll_params[clk_index].m << PLL_REGM_SHIFT; omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val); val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4); val &= ~PLL_REGM_F_MASK; val |= omap_usb3_dpll_params[clk_index].mf << PLL_REGM_F_SHIFT; omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val); val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3); val &= ~PLL_SD_MASK; val |= omap_usb3_dpll_params[clk_index].sd << PLL_SD_SHIFT; omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val); omap_usb_dpll_relock(phy); return 0; }
static int omap_usb3_suspend(struct usb_phy *x, int suspend) { struct omap_usb *phy = phy_to_omapusb(x); int val; int timeout = PLL_IDLE_TIME; if (suspend && !phy->is_suspended) { val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); val |= PLL_IDLE; omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val); do { val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS); if (val & PLL_TICOPWDN) break; udelay(1); } while (--timeout); omap_control_usb3_phy_power(phy->control_dev, 0); phy->is_suspended = 1; } else if (!suspend && phy->is_suspended) { phy->is_suspended = 0; val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); val &= ~PLL_IDLE; omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val); do { val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS); if (!(val & PLL_TICOPWDN)) break; udelay(1); } while (--timeout); } return 0; }
static void omap_usb_dpll_relock(struct omap_usb *phy) { u32 val; unsigned long timeout; omap_usb_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO); timeout = jiffies + msecs_to_jiffies(20); do { val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS); if (val & PLL_LOCK) break; } while (!WARN_ON(time_after(jiffies, timeout))); }
static int omap_usb_init(struct phy *x) { struct omap_usb *phy = phy_get_drvdata(x); u32 val; if (phy->flags & OMAP_USB2_CALIBRATE_FALSE_DISCONNECT) { /* * * Reduce the sensitivity of internal PHY by enabling the * DISCON_BYP_LATCH of the USB2PHY_ANA_CONFIG1 register. This * resolves issues with certain devices which can otherwise * be prone to false disconnects. * */ val = omap_usb_readl(phy->phy_base, USB2PHY_ANA_CONFIG1); val |= USB2PHY_DISCON_BYP_LATCH; omap_usb_writel(phy->phy_base, USB2PHY_ANA_CONFIG1, val); } return 0; }