Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

phy: samsung-ufs: convert phy clk usage to clk_bulk API

Instead of using separated clock manipulation, this converts the phy
clock usage to be clk_bulk APIs. By using this, we can completely
remove has_symbol_clk check and symbol clk variables.
Furthermore, clk_get should be moved to probe because there is no need
to get them in the phy_init callback.

Signed-off-by: Chanho Park <chanho61.park@samsung.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Link: https://lore.kernel.org/r/20220706020255.151177-2-chanho61.park@samsung.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Chanho Park and committed by
Vinod Koul
8d5bb683 c1ab64aa

+42 -88
+6 -1
drivers/phy/samsung/phy-exynos7-ufs.c
··· 68 68 [CFG_POST_PWR_HS] = exynos7_post_pwr_hs_cfg, 69 69 }; 70 70 71 + static const char * const exynos7_ufs_phy_clks[] = { 72 + "tx0_symbol_clk", "rx0_symbol_clk", "rx1_symbol_clk", "ref_clk", 73 + }; 74 + 71 75 const struct samsung_ufs_phy_drvdata exynos7_ufs_phy = { 72 76 .cfgs = exynos7_ufs_phy_cfgs, 73 77 .isol = { ··· 79 75 .mask = EXYNOS7_EMBEDDED_COMBO_PHY_CTRL_MASK, 80 76 .en = EXYNOS7_EMBEDDED_COMBO_PHY_CTRL_EN, 81 77 }, 82 - .has_symbol_clk = 1, 78 + .clk_list = exynos7_ufs_phy_clks, 79 + .num_clks = ARRAY_SIZE(exynos7_ufs_phy_clks), 83 80 .cdr_lock_status_offset = EXYNOS7_EMBEDDED_COMBO_PHY_CDR_LOCK_STATUS, 84 81 };
+6 -1
drivers/phy/samsung/phy-exynosautov9-ufs.c
··· 57 57 [CFG_PRE_PWR_HS] = exynosautov9_pre_pwr_hs_cfg, 58 58 }; 59 59 60 + static const char * const exynosautov9_ufs_phy_clks[] = { 61 + "ref_clk", 62 + }; 63 + 60 64 const struct samsung_ufs_phy_drvdata exynosautov9_ufs_phy = { 61 65 .cfgs = exynosautov9_ufs_phy_cfgs, 62 66 .isol = { ··· 68 64 .mask = EXYNOSAUTOV9_EMBEDDED_COMBO_PHY_CTRL_MASK, 69 65 .en = EXYNOSAUTOV9_EMBEDDED_COMBO_PHY_CTRL_EN, 70 66 }, 71 - .has_symbol_clk = 0, 67 + .clk_list = exynosautov9_ufs_phy_clks, 68 + .num_clks = ARRAY_SIZE(exynosautov9_ufs_phy_clks), 72 69 .cdr_lock_status_offset = EXYNOSAUTOV9_EMBEDDED_COMBO_PHY_CDR_LOCK_STATUS, 73 70 };
+6 -1
drivers/phy/samsung/phy-fsd-ufs.c
··· 46 46 [CFG_POST_PWR_HS] = fsd_post_pwr_hs_cfg, 47 47 }; 48 48 49 + static const char * const fsd_ufs_phy_clks[] = { 50 + "ref_clk", 51 + }; 52 + 49 53 const struct samsung_ufs_phy_drvdata fsd_ufs_phy = { 50 54 .cfgs = fsd_ufs_phy_cfgs, 51 55 .isol = { ··· 57 53 .mask = FSD_EMBEDDED_COMBO_PHY_CTRL_MASK, 58 54 .en = FSD_EMBEDDED_COMBO_PHY_CTRL_EN, 59 55 }, 60 - .has_symbol_clk = 0, 56 + .clk_list = fsd_ufs_phy_clks, 57 + .num_clks = ARRAY_SIZE(fsd_ufs_phy_clks), 61 58 .cdr_lock_status_offset = FSD_EMBEDDED_COMBO_PHY_CDR_LOCK_STATUS, 62 59 };
+21 -78
drivers/phy/samsung/phy-samsung-ufs.c
··· 131 131 return err; 132 132 } 133 133 134 - static int samsung_ufs_phy_symbol_clk_init(struct samsung_ufs_phy *phy) 135 - { 136 - int ret; 137 - 138 - phy->tx0_symbol_clk = devm_clk_get(phy->dev, "tx0_symbol_clk"); 139 - if (IS_ERR(phy->tx0_symbol_clk)) { 140 - dev_err(phy->dev, "failed to get tx0_symbol_clk clock\n"); 141 - return PTR_ERR(phy->tx0_symbol_clk); 142 - } 143 - 144 - phy->rx0_symbol_clk = devm_clk_get(phy->dev, "rx0_symbol_clk"); 145 - if (IS_ERR(phy->rx0_symbol_clk)) { 146 - dev_err(phy->dev, "failed to get rx0_symbol_clk clock\n"); 147 - return PTR_ERR(phy->rx0_symbol_clk); 148 - } 149 - 150 - phy->rx1_symbol_clk = devm_clk_get(phy->dev, "rx1_symbol_clk"); 151 - if (IS_ERR(phy->rx1_symbol_clk)) { 152 - dev_err(phy->dev, "failed to get rx1_symbol_clk clock\n"); 153 - return PTR_ERR(phy->rx1_symbol_clk); 154 - } 155 - 156 - ret = clk_prepare_enable(phy->tx0_symbol_clk); 157 - if (ret) { 158 - dev_err(phy->dev, "%s: tx0_symbol_clk enable failed %d\n", __func__, ret); 159 - goto out; 160 - } 161 - 162 - ret = clk_prepare_enable(phy->rx0_symbol_clk); 163 - if (ret) { 164 - dev_err(phy->dev, "%s: rx0_symbol_clk enable failed %d\n", __func__, ret); 165 - goto out_disable_tx0_clk; 166 - } 167 - 168 - ret = clk_prepare_enable(phy->rx1_symbol_clk); 169 - if (ret) { 170 - dev_err(phy->dev, "%s: rx1_symbol_clk enable failed %d\n", __func__, ret); 171 - goto out_disable_rx0_clk; 172 - } 173 - 174 - return 0; 175 - 176 - out_disable_rx0_clk: 177 - clk_disable_unprepare(phy->rx0_symbol_clk); 178 - out_disable_tx0_clk: 179 - clk_disable_unprepare(phy->tx0_symbol_clk); 180 - out: 181 - return ret; 182 - } 183 - 184 134 static int samsung_ufs_phy_clks_init(struct samsung_ufs_phy *phy) 185 135 { 186 - int ret; 136 + int i; 137 + const struct samsung_ufs_phy_drvdata *drvdata = phy->drvdata; 138 + int num_clks = drvdata->num_clks; 187 139 188 - phy->ref_clk = devm_clk_get(phy->dev, "ref_clk"); 189 - if (IS_ERR(phy->ref_clk)) 190 - dev_err(phy->dev, "failed to get ref_clk clock\n"); 140 + phy->clks = devm_kcalloc(phy->dev, num_clks, sizeof(*phy->clks), 141 + GFP_KERNEL); 142 + if (!phy->clks) 143 + return -ENOMEM; 191 144 192 - ret = clk_prepare_enable(phy->ref_clk); 193 - if (ret) { 194 - dev_err(phy->dev, "%s: ref_clk enable failed %d\n", __func__, ret); 195 - return ret; 196 - } 145 + for (i = 0; i < num_clks; i++) 146 + phy->clks[i].id = drvdata->clk_list[i]; 197 147 198 - dev_dbg(phy->dev, "UFS MPHY ref_clk_rate = %ld\n", clk_get_rate(phy->ref_clk)); 199 - 200 - return 0; 148 + return devm_clk_bulk_get(phy->dev, num_clks, phy->clks); 201 149 } 202 150 203 151 static int samsung_ufs_phy_init(struct phy *phy) ··· 156 208 ss_phy->lane_cnt = phy->attrs.bus_width; 157 209 ss_phy->ufs_phy_state = CFG_PRE_INIT; 158 210 159 - if (ss_phy->has_symbol_clk) { 160 - ret = samsung_ufs_phy_symbol_clk_init(ss_phy); 161 - if (ret) 162 - dev_err(ss_phy->dev, "failed to set ufs phy symbol clocks\n"); 211 + ret = clk_bulk_prepare_enable(ss_phy->drvdata->num_clks, ss_phy->clks); 212 + if (ret) { 213 + dev_err(ss_phy->dev, "failed to enable ufs phy clocks\n"); 214 + return ret; 163 215 } 164 - 165 - ret = samsung_ufs_phy_clks_init(ss_phy); 166 - if (ret) 167 - dev_err(ss_phy->dev, "failed to set ufs phy clocks\n"); 168 216 169 217 ret = samsung_ufs_phy_calibrate(phy); 170 218 if (ret) ··· 202 258 { 203 259 struct samsung_ufs_phy *ss_phy = get_samsung_ufs_phy(phy); 204 260 205 - clk_disable_unprepare(ss_phy->ref_clk); 206 - 207 - if (ss_phy->has_symbol_clk) { 208 - clk_disable_unprepare(ss_phy->tx0_symbol_clk); 209 - clk_disable_unprepare(ss_phy->rx0_symbol_clk); 210 - clk_disable_unprepare(ss_phy->rx1_symbol_clk); 211 - } 261 + clk_bulk_disable_unprepare(ss_phy->drvdata->num_clks, ss_phy->clks); 212 262 213 263 return 0; 214 264 } ··· 268 330 phy->dev = dev; 269 331 phy->drvdata = drvdata; 270 332 phy->cfgs = drvdata->cfgs; 271 - phy->has_symbol_clk = drvdata->has_symbol_clk; 272 333 memcpy(&phy->isol, &drvdata->isol, sizeof(phy->isol)); 273 334 274 335 if (!of_property_read_u32_index(dev->of_node, "samsung,pmu-syscon", 1, ··· 275 338 phy->isol.offset = isol_offset; 276 339 277 340 phy->lane_cnt = PHY_DEF_LANE_CNT; 341 + 342 + err = samsung_ufs_phy_clks_init(phy); 343 + if (err) { 344 + dev_err(dev, "failed to get phy clocks\n"); 345 + goto out; 346 + } 278 347 279 348 phy_set_drvdata(gen_phy, phy); 280 349
+3 -7
drivers/phy/samsung/phy-samsung-ufs.h
··· 109 109 struct samsung_ufs_phy_drvdata { 110 110 const struct samsung_ufs_phy_cfg **cfgs; 111 111 struct samsung_ufs_phy_pmu_isol isol; 112 - bool has_symbol_clk; 112 + const char * const *clk_list; 113 + int num_clks; 113 114 u32 cdr_lock_status_offset; 114 115 }; 115 116 ··· 118 117 struct device *dev; 119 118 void __iomem *reg_pma; 120 119 struct regmap *reg_pmu; 121 - struct clk *ref_clk; 122 - struct clk *ref_clk_parent; 123 - struct clk *tx0_symbol_clk; 124 - struct clk *rx0_symbol_clk; 125 - struct clk *rx1_symbol_clk; 120 + struct clk_bulk_data *clks; 126 121 const struct samsung_ufs_phy_drvdata *drvdata; 127 122 const struct samsung_ufs_phy_cfg * const *cfgs; 128 123 struct samsung_ufs_phy_pmu_isol isol; 129 - bool has_symbol_clk; 130 124 u8 lane_cnt; 131 125 int ufs_phy_state; 132 126 enum phy_mode mode;