diff --git a/arch/arm64/boot/dts/exynos/exynos7.dtsi b/arch/arm64/boot/dts/exynos/exynos7.dtsi index a9531c4bf22f..9a4dd9ae5cdf 100644 --- a/arch/arm64/boot/dts/exynos/exynos7.dtsi +++ b/arch/arm64/boot/dts/exynos/exynos7.dtsi @@ -665,9 +665,14 @@ reg-names = "phy-pma"; samsung,pmu-syscon = <&pmu_system_controller>; #phy-cells = <0>; - clocks = <&clock_fsys1 MOUT_FSYS1_PHYCLK_SEL1>, - <&clock_top1 CLK_SCLK_PHY_FSYS1_26M>; - clock-names = "ref_clk_parent", "ref_clk"; + clocks = <&clock_top1 DOUT_SCLK_PHY_FSYS1_26M>, + <&clock_fsys1 SCLK_COMBO_PHY_EMBEDDED_26M>, + <&clock_fsys1 PHYCLK_UFS20_RX1_SYMBOL_USER>, + <&clock_fsys1 PHYCLK_UFS20_RX0_SYMBOL_USER>, + <&clock_fsys1 PHYCLK_UFS20_TX0_SYMBOL_USER>; + clock-names = "ref_clk_parent", "ref_clk", + "rx1_symbol_clk", "rx0_symbol_clk", + "tx0_symbol_clk"; }; usbdrd_phy: phy@15500000 { diff --git a/drivers/phy/samsung/phy-samsung-ufs.c b/drivers/phy/samsung/phy-samsung-ufs.c index 572e40e72776..2d5dcd670927 100644 --- a/drivers/phy/samsung/phy-samsung-ufs.c +++ b/drivers/phy/samsung/phy-samsung-ufs.c @@ -136,9 +136,63 @@ int samsung_ufs_phy_calibrate(struct phy *phy) return err; } +static int samsung_ufs_phy_symbol_clk_init(struct samsung_ufs_phy *phy) +{ + struct clk *clk; + int ret = 0; + + clk = devm_clk_get(phy->dev, "tx0_symbol_clk"); + if (IS_ERR(clk)) { + dev_err(phy->dev, "failed to get tx0_symbol_clk clock\n"); + goto out; + } else { + phy->tx0_symbol_clk = clk; + } + + clk = devm_clk_get(phy->dev, "rx0_symbol_clk"); + if (IS_ERR(clk)) { + dev_err(phy->dev, "failed to get rx0_symbol_clk clock\n"); + goto out; + } else { + phy->rx0_symbol_clk = clk; + } + + clk = devm_clk_get(phy->dev, "rx1_symbol_clk"); + if (IS_ERR(clk)) { + dev_err(phy->dev, "failed to get rx1_symbol_clk clock\n"); + goto out; + } else { + phy->rx1_symbol_clk = clk; + } + + ret = clk_prepare_enable(phy->tx0_symbol_clk); + if (ret) { + dev_err(phy->dev, "%s: tx0_symbol_clk enable failed %d\n", + __func__, ret); + goto out; + } + ret = clk_prepare_enable(phy->rx0_symbol_clk); + if (ret) { + dev_err(phy->dev, "%s: rx0_symbol_clk enable failed %d\n", + __func__, ret); + goto out; + } + ret = clk_prepare_enable(phy->rx1_symbol_clk); + if (ret) { + dev_err(phy->dev, "%s: rx1_symbol_clk enable failed %d\n", + __func__, ret); + goto out; + } +out: + return ret; +} + static int samsung_ufs_phy_clks_init(struct samsung_ufs_phy *phy) { struct clk *child, *parent; + u32 phy_clk_rate, phy_parent_rate; + int ret; + child = devm_clk_get(phy->dev, "ref_clk"); if (IS_ERR(child)) @@ -146,18 +200,32 @@ static int samsung_ufs_phy_clks_init(struct samsung_ufs_phy *phy) else phy->ref_clk = child; + ret = clk_prepare_enable(phy->ref_clk); + if (ret) { + dev_err(phy->dev, "%s: ref_clk enable failed %d\n", + __func__, ret); + return ret; + } + + phy_clk_rate = clk_get_rate(child); + dev_info(phy->dev, "MPHY ref_clk_rate = %d\n", phy_clk_rate); + parent = devm_clk_get(phy->dev, "ref_clk_parent"); if (IS_ERR(parent)) dev_err(phy->dev, "failed to get ref_clk_parent clock\n"); else phy->ref_clk_parent = parent; + phy_parent_rate = clk_get_rate(parent); + dev_info(phy->dev, "MPHY ref_parent_clk_rate = %d\n", phy_parent_rate); + return clk_set_parent(child, parent); } static int samsung_ufs_phy_init(struct phy *phy) { struct samsung_ufs_phy *_phy = get_samsung_ufs_phy(phy); + int ret; _phy->lane_cnt = phy->attrs.bus_width; _phy->ufs_phy_state = CFG_PRE_INIT; @@ -167,7 +235,13 @@ static int samsung_ufs_phy_init(struct phy *phy) _phy->is_pre_pmc = false; _phy->is_post_pmc = false; - samsung_ufs_phy_clks_init(_phy); + ret = samsung_ufs_phy_symbol_clk_init(_phy); + if (ret) + dev_err(_phy->dev, "failed to set ufs phy symbol clocks\n"); + + ret = samsung_ufs_phy_clks_init(_phy); + if (!ret) + dev_err(_phy->dev, "failed to set ufs phy clocks\n"); samsung_ufs_phy_calibrate(phy); @@ -177,14 +251,6 @@ static int samsung_ufs_phy_init(struct phy *phy) static int samsung_ufs_phy_power_on(struct phy *phy) { struct samsung_ufs_phy *_phy = get_samsung_ufs_phy(phy); - int ret; - - ret = clk_prepare_enable(_phy->ref_clk); - if (ret) { - dev_err(_phy->dev, "%s: ref_clk enable failed %d\n", - __func__, ret); - return ret; - } samsung_ufs_phy_ctrl_isol(_phy, false); return 0; diff --git a/drivers/phy/samsung/phy-samsung-ufs.h b/drivers/phy/samsung/phy-samsung-ufs.h index 971d67ae7f80..27dc1b573469 100644 --- a/drivers/phy/samsung/phy-samsung-ufs.h +++ b/drivers/phy/samsung/phy-samsung-ufs.h @@ -110,6 +110,9 @@ struct samsung_ufs_phy { struct regmap *reg_pmu; struct clk *ref_clk; struct clk *ref_clk_parent; + struct clk *tx0_symbol_clk; + struct clk *rx0_symbol_clk; + struct clk *rx1_symbol_clk; const struct samsung_ufs_phy_drvdata *drvdata; struct samsung_ufs_phy_cfg **cfg; const struct pmu_isol *isol;