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

clk: qcom: rcg2: Add support for display port clock ops

New display port clock ops supported for display port clocks.

Signed-off-by: Taniya Das <tdas@codeaurora.org>
Link: https://lkml.kernel.org/r/20190731182713.8123-2-tdas@codeaurora.org
Signed-off-by: Stephen Boyd <sboyd@kernel.org>

authored by

Taniya Das and committed by
Stephen Boyd
cddf1f82 e42617b8

+79
+1
drivers/clk/qcom/Kconfig
··· 14 14 tristate "Support for Qualcomm's clock controllers" 15 15 depends on OF 16 16 depends on ARCH_QCOM || COMPILE_TEST 17 + select RATIONAL 17 18 select REGMAP_MMIO 18 19 select RESET_CONTROLLER 19 20
+1
drivers/clk/qcom/clk-rcg.h
··· 161 161 extern const struct clk_ops clk_pixel_ops; 162 162 extern const struct clk_ops clk_gfx3d_ops; 163 163 extern const struct clk_ops clk_rcg2_shared_ops; 164 + extern const struct clk_ops clk_dp_ops; 164 165 165 166 struct clk_rcg_dfs_data { 166 167 struct clk_rcg2 *rcg;
+77
drivers/clk/qcom/clk-rcg2.c
··· 10 10 #include <linux/export.h> 11 11 #include <linux/clk-provider.h> 12 12 #include <linux/delay.h> 13 + #include <linux/rational.h> 13 14 #include <linux/regmap.h> 14 15 #include <linux/math64.h> 15 16 #include <linux/slab.h> ··· 1125 1124 return 0; 1126 1125 } 1127 1126 EXPORT_SYMBOL_GPL(qcom_cc_register_rcg_dfs); 1127 + 1128 + static int clk_rcg2_dp_set_rate(struct clk_hw *hw, unsigned long rate, 1129 + unsigned long parent_rate) 1130 + { 1131 + struct clk_rcg2 *rcg = to_clk_rcg2(hw); 1132 + struct freq_tbl f = { 0 }; 1133 + u32 mask = BIT(rcg->hid_width) - 1; 1134 + u32 hid_div, cfg; 1135 + int i, num_parents = clk_hw_get_num_parents(hw); 1136 + unsigned long num, den; 1137 + 1138 + rational_best_approximation(parent_rate, rate, 1139 + GENMASK(rcg->mnd_width - 1, 0), 1140 + GENMASK(rcg->mnd_width - 1, 0), &den, &num); 1141 + 1142 + if (!num || !den) 1143 + return -EINVAL; 1144 + 1145 + regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, &cfg); 1146 + hid_div = cfg; 1147 + cfg &= CFG_SRC_SEL_MASK; 1148 + cfg >>= CFG_SRC_SEL_SHIFT; 1149 + 1150 + for (i = 0; i < num_parents; i++) { 1151 + if (cfg == rcg->parent_map[i].cfg) { 1152 + f.src = rcg->parent_map[i].src; 1153 + break; 1154 + } 1155 + } 1156 + 1157 + f.pre_div = hid_div; 1158 + f.pre_div >>= CFG_SRC_DIV_SHIFT; 1159 + f.pre_div &= mask; 1160 + 1161 + if (num != den) { 1162 + f.m = num; 1163 + f.n = den; 1164 + } else { 1165 + f.m = 0; 1166 + f.n = 0; 1167 + } 1168 + 1169 + return clk_rcg2_configure(rcg, &f); 1170 + } 1171 + 1172 + static int clk_rcg2_dp_set_rate_and_parent(struct clk_hw *hw, 1173 + unsigned long rate, unsigned long parent_rate, u8 index) 1174 + { 1175 + return clk_rcg2_dp_set_rate(hw, rate, parent_rate); 1176 + } 1177 + 1178 + static int clk_rcg2_dp_determine_rate(struct clk_hw *hw, 1179 + struct clk_rate_request *req) 1180 + { 1181 + struct clk_rate_request parent_req = *req; 1182 + int ret; 1183 + 1184 + ret = __clk_determine_rate(clk_hw_get_parent(hw), &parent_req); 1185 + if (ret) 1186 + return ret; 1187 + 1188 + req->best_parent_rate = parent_req.rate; 1189 + 1190 + return 0; 1191 + } 1192 + 1193 + const struct clk_ops clk_dp_ops = { 1194 + .is_enabled = clk_rcg2_is_enabled, 1195 + .get_parent = clk_rcg2_get_parent, 1196 + .set_parent = clk_rcg2_set_parent, 1197 + .recalc_rate = clk_rcg2_recalc_rate, 1198 + .set_rate = clk_rcg2_dp_set_rate, 1199 + .set_rate_and_parent = clk_rcg2_dp_set_rate_and_parent, 1200 + .determine_rate = clk_rcg2_dp_determine_rate, 1201 + }; 1202 + EXPORT_SYMBOL_GPL(clk_dp_ops);