static int ti_pipe3_exit(struct phy *x) { struct ti_pipe3 *phy = phy_get_drvdata(x); u32 val; unsigned long timeout; /* SATA DPLL can't be powered down due to Errata i783 and PCIe * does not have internal DPLL */ if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata") || of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie")) return 0; /* Put DPLL in IDLE mode */ val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); val |= PLL_IDLE; ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val); /* wait for LDO and Oscillator to power down */ timeout = jiffies + msecs_to_jiffies(PLL_IDLE_TIME); do { cpu_relax(); val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS); if ((val & PLL_TICOPWDN) && (val & PLL_LDOPWDN)) break; } while (!time_after(jiffies, timeout)); if (!(val & PLL_TICOPWDN) || !(val & PLL_LDOPWDN)) { dev_err(phy->dev, "Failed to power down: PLL_STATUS 0x%x\n", val); return -EBUSY; } return 0; }
static int ti_pipe3_init(struct phy *x) { struct ti_pipe3 *phy = phy_get_drvdata(x); u32 val; int ret = 0; /* * Set pcie_pcs register to 0x96 for proper functioning of phy * as recommended in AM572x TRM SPRUHZ6, section 18.5.2.2, table * 18-1804. */ if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie")) { omap_control_pcie_pcs(phy->control_dev, 0x96); return 0; } /* Bring it out of IDLE if it is IDLE */ val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); if (val & PLL_IDLE) { val &= ~PLL_IDLE; ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val); ret = ti_pipe3_dpll_wait_lock(phy); } /* Program the DPLL only if not locked */ val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS); if (!(val & PLL_LOCK)) if (ti_pipe3_dpll_program(phy)) return -EINVAL; return ret; }
static int ti_pipe3_exit(struct phy *x) { struct ti_pipe3 *phy = phy_get_drvdata(x); u32 val; unsigned long timeout; /* If dpll_reset_syscon is not present we wont power down SATA DPLL * due to Errata i783 */ if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata") && !phy->dpll_reset_syscon) return 0; if (!of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie")) { /* Put DPLL in IDLE mode */ val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); val |= PLL_IDLE; ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val); /* wait for LDO and Oscillator to power down */ timeout = jiffies + msecs_to_jiffies(PLL_IDLE_TIME); do { cpu_relax(); val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS); if ((val & PLL_TICOPWDN) && (val & PLL_LDOPWDN)) break; } while (!time_after(jiffies, timeout)); if (!(val & PLL_TICOPWDN) || !(val & PLL_LDOPWDN)) { dev_err(phy->dev, "Failed to power down: PLL_STATUS 0x%x\n", val); return -EBUSY; } } /* i783: SATA needs control bit toggle after PLL unlock */ if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata")) { regmap_update_bits(phy->dpll_reset_syscon, phy->dpll_reset_reg, SATA_PLL_SOFT_RESET, SATA_PLL_SOFT_RESET); regmap_update_bits(phy->dpll_reset_syscon, phy->dpll_reset_reg, SATA_PLL_SOFT_RESET, 0); } ti_pipe3_disable_clocks(phy); return 0; }
static int ti_pipe3_dpll_program(struct ti_pipe3 *phy) { u32 val; struct pipe3_dpll_params *dpll_params; dpll_params = ti_pipe3_get_dpll_params(phy); if (!dpll_params) return -EINVAL; val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1); val &= ~PLL_REGN_MASK; val |= dpll_params->n << PLL_REGN_SHIFT; ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val); val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); val &= ~PLL_SELFREQDCO_MASK; val |= dpll_params->freq << PLL_SELFREQDCO_SHIFT; ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val); val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1); val &= ~PLL_REGM_MASK; val |= dpll_params->m << PLL_REGM_SHIFT; ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val); val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4); val &= ~PLL_REGM_F_MASK; val |= dpll_params->mf << PLL_REGM_F_SHIFT; ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val); val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3); val &= ~PLL_SD_MASK; val |= dpll_params->sd << PLL_SD_SHIFT; ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val); ti_pipe3_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO); return ti_pipe3_dpll_wait_lock(phy); }