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

clk: add support for clock reparent on set_rate

Add core support to allow clock implementations to select the best
parent clock when rounding a rate, e.g. the one which can provide the
closest clock rate to that requested. This is by way of adding a new
clock op, determine_rate(), which is like round_rate() but has an extra
parameter to allow the clock implementation to optionally select a
different parent clock. The core then takes care of reparenting the
clock when setting the rate.

The parent change takes place with the help of some new private data
members. struct clk::new_parent specifies a clock's new parent (NULL
indicates no change), and struct clk::new_child specifies a clock's new
child (whose new_parent member points back to it). The purpose of these
are to allow correct walking of the future tree for notifications prior
to actually reparenting any clocks, specifically to skip child clocks
who are being reparented to another clock (they will be notified via the
new parent), and to include any new child clock. These pointers are set
by clk_calc_subtree(), and the new_child pointer gets cleared when a
child is actually reparented to avoid duplicate POST_RATE_CHANGE
notifications.

Each place where round_rate() is called, determine_rate() is checked
first and called in preference. This restructures a few of the call
sites to simplify the logic into if/else blocks.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Cc: Mike Turquette <mturquette@linaro.org>
Cc: linux-arm-kernel@lists.infradead.org
Signed-off-by: Mike Turquette <mturquette@linaro.org>

authored by

James Hogan and committed by
Mike Turquette
71472c0c 4935b22c

+130 -64
+26 -20
Documentation/clk.txt
··· 70 70 unsigned long parent_rate); 71 71 long (*round_rate)(struct clk_hw *hw, unsigned long, 72 72 unsigned long *); 73 + long (*determine_rate)(struct clk_hw *hw, 74 + unsigned long rate, 75 + unsigned long *best_parent_rate, 76 + struct clk **best_parent_clk); 73 77 int (*set_parent)(struct clk_hw *hw, u8 index); 74 78 u8 (*get_parent)(struct clk_hw *hw); 75 79 int (*set_rate)(struct clk_hw *hw, unsigned long); ··· 183 179 callback is invalid or otherwise unnecessary. Empty cells are either 184 180 optional or must be evaluated on a case-by-case basis. 185 181 186 - clock hardware characteristics 187 - ----------------------------------------------------------- 188 - | gate | change rate | single parent | multiplexer | root | 189 - |------|-------------|---------------|-------------|------| 190 - .prepare | | | | | | 191 - .unprepare | | | | | | 192 - | | | | | | 193 - .enable | y | | | | | 194 - .disable | y | | | | | 195 - .is_enabled | y | | | | | 196 - | | | | | | 197 - .recalc_rate | | y | | | | 198 - .round_rate | | y | | | | 199 - .set_rate | | y | | | | 200 - | | | | | | 201 - .set_parent | | | n | y | n | 202 - .get_parent | | | n | y | n | 203 - | | | | | | 204 - .init | | | | | | 205 - ----------------------------------------------------------- 182 + clock hardware characteristics 183 + ----------------------------------------------------------- 184 + | gate | change rate | single parent | multiplexer | root | 185 + |------|-------------|---------------|-------------|------| 186 + .prepare | | | | | | 187 + .unprepare | | | | | | 188 + | | | | | | 189 + .enable | y | | | | | 190 + .disable | y | | | | | 191 + .is_enabled | y | | | | | 192 + | | | | | | 193 + .recalc_rate | | y | | | | 194 + .round_rate | | y [1] | | | | 195 + .determine_rate | | y [1] | | | | 196 + .set_rate | | y | | | | 197 + | | | | | | 198 + .set_parent | | | n | y | n | 199 + .get_parent | | | n | y | n | 200 + | | | | | | 201 + .init | | | | | | 202 + ----------------------------------------------------------- 203 + [1] either one of round_rate or determine_rate is required. 206 204 207 205 Finally, register your clock at run-time with a hardware-specific 208 206 registration function. This function simply populates struct clk_foo's
+94 -44
drivers/clk/clk.c
··· 889 889 unsigned long __clk_round_rate(struct clk *clk, unsigned long rate) 890 890 { 891 891 unsigned long parent_rate = 0; 892 + struct clk *parent; 892 893 893 894 if (!clk) 894 895 return 0; 895 896 896 - if (!clk->ops->round_rate) { 897 - if (clk->flags & CLK_SET_RATE_PARENT) 898 - return __clk_round_rate(clk->parent, rate); 899 - else 900 - return clk->rate; 901 - } 897 + parent = clk->parent; 898 + if (parent) 899 + parent_rate = parent->rate; 902 900 903 - if (clk->parent) 904 - parent_rate = clk->parent->rate; 905 - 906 - return clk->ops->round_rate(clk->hw, rate, &parent_rate); 901 + if (clk->ops->determine_rate) 902 + return clk->ops->determine_rate(clk->hw, rate, &parent_rate, 903 + &parent); 904 + else if (clk->ops->round_rate) 905 + return clk->ops->round_rate(clk->hw, rate, &parent_rate); 906 + else if (clk->flags & CLK_SET_RATE_PARENT) 907 + return __clk_round_rate(clk->parent, rate); 908 + else 909 + return clk->rate; 907 910 } 908 911 909 912 /** ··· 1059 1056 1060 1057 static void clk_reparent(struct clk *clk, struct clk *new_parent) 1061 1058 { 1059 + /* avoid duplicate POST_RATE_CHANGE notifications */ 1060 + if (new_parent->new_child == clk) 1061 + new_parent->new_child = NULL; 1062 + 1062 1063 hlist_del(&clk->child_node); 1063 1064 1064 1065 if (new_parent) ··· 1183 1176 return ret; 1184 1177 } 1185 1178 1186 - static void clk_calc_subtree(struct clk *clk, unsigned long new_rate) 1179 + static void clk_calc_subtree(struct clk *clk, unsigned long new_rate, 1180 + struct clk *new_parent, u8 p_index) 1187 1181 { 1188 1182 struct clk *child; 1189 1183 1190 1184 clk->new_rate = new_rate; 1185 + clk->new_parent = new_parent; 1186 + clk->new_parent_index = p_index; 1187 + /* include clk in new parent's PRE_RATE_CHANGE notifications */ 1188 + clk->new_child = NULL; 1189 + if (new_parent && new_parent != clk->parent) 1190 + new_parent->new_child = clk; 1191 1191 1192 1192 hlist_for_each_entry(child, &clk->children, child_node) { 1193 1193 if (child->ops->recalc_rate) 1194 1194 child->new_rate = child->ops->recalc_rate(child->hw, new_rate); 1195 1195 else 1196 1196 child->new_rate = new_rate; 1197 - clk_calc_subtree(child, child->new_rate); 1197 + clk_calc_subtree(child, child->new_rate, NULL, 0); 1198 1198 } 1199 1199 } 1200 1200 ··· 1212 1198 static struct clk *clk_calc_new_rates(struct clk *clk, unsigned long rate) 1213 1199 { 1214 1200 struct clk *top = clk; 1201 + struct clk *old_parent, *parent; 1215 1202 unsigned long best_parent_rate = 0; 1216 1203 unsigned long new_rate; 1204 + u8 p_index = 0; 1217 1205 1218 1206 /* sanity */ 1219 1207 if (IS_ERR_OR_NULL(clk)) 1220 1208 return NULL; 1221 1209 1222 1210 /* save parent rate, if it exists */ 1223 - if (clk->parent) 1224 - best_parent_rate = clk->parent->rate; 1211 + parent = old_parent = clk->parent; 1212 + if (parent) 1213 + best_parent_rate = parent->rate; 1225 1214 1226 - /* never propagate up to the parent */ 1227 - if (!(clk->flags & CLK_SET_RATE_PARENT)) { 1228 - if (!clk->ops->round_rate) { 1229 - clk->new_rate = clk->rate; 1230 - return NULL; 1231 - } 1232 - new_rate = clk->ops->round_rate(clk->hw, rate, &best_parent_rate); 1215 + /* find the closest rate and parent clk/rate */ 1216 + if (clk->ops->determine_rate) { 1217 + new_rate = clk->ops->determine_rate(clk->hw, rate, 1218 + &best_parent_rate, 1219 + &parent); 1220 + } else if (clk->ops->round_rate) { 1221 + new_rate = clk->ops->round_rate(clk->hw, rate, 1222 + &best_parent_rate); 1223 + } else if (!parent || !(clk->flags & CLK_SET_RATE_PARENT)) { 1224 + /* pass-through clock without adjustable parent */ 1225 + clk->new_rate = clk->rate; 1226 + return NULL; 1227 + } else { 1228 + /* pass-through clock with adjustable parent */ 1229 + top = clk_calc_new_rates(parent, rate); 1230 + new_rate = parent->new_rate; 1233 1231 goto out; 1234 1232 } 1235 1233 1236 - /* need clk->parent from here on out */ 1237 - if (!clk->parent) { 1238 - pr_debug("%s: %s has NULL parent\n", __func__, clk->name); 1234 + /* some clocks must be gated to change parent */ 1235 + if (parent != old_parent && 1236 + (clk->flags & CLK_SET_PARENT_GATE) && clk->prepare_count) { 1237 + pr_debug("%s: %s not gated but wants to reparent\n", 1238 + __func__, clk->name); 1239 1239 return NULL; 1240 1240 } 1241 1241 1242 - if (!clk->ops->round_rate) { 1243 - top = clk_calc_new_rates(clk->parent, rate); 1244 - new_rate = clk->parent->new_rate; 1245 - 1246 - goto out; 1242 + /* try finding the new parent index */ 1243 + if (parent) { 1244 + p_index = clk_fetch_parent_index(clk, parent); 1245 + if (p_index == clk->num_parents) { 1246 + pr_debug("%s: clk %s can not be parent of clk %s\n", 1247 + __func__, parent->name, clk->name); 1248 + return NULL; 1249 + } 1247 1250 } 1248 1251 1249 - new_rate = clk->ops->round_rate(clk->hw, rate, &best_parent_rate); 1250 - 1251 - if (best_parent_rate != clk->parent->rate) { 1252 - top = clk_calc_new_rates(clk->parent, best_parent_rate); 1253 - 1254 - goto out; 1255 - } 1252 + if ((clk->flags & CLK_SET_RATE_PARENT) && parent && 1253 + best_parent_rate != parent->rate) 1254 + top = clk_calc_new_rates(parent, best_parent_rate); 1256 1255 1257 1256 out: 1258 - clk_calc_subtree(clk, new_rate); 1257 + clk_calc_subtree(clk, new_rate, parent, p_index); 1259 1258 1260 1259 return top; 1261 1260 } ··· 1280 1253 */ 1281 1254 static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long event) 1282 1255 { 1283 - struct clk *child, *fail_clk = NULL; 1256 + struct clk *child, *tmp_clk, *fail_clk = NULL; 1284 1257 int ret = NOTIFY_DONE; 1285 1258 1286 1259 if (clk->rate == clk->new_rate) ··· 1293 1266 } 1294 1267 1295 1268 hlist_for_each_entry(child, &clk->children, child_node) { 1296 - clk = clk_propagate_rate_change(child, event); 1297 - if (clk) 1298 - fail_clk = clk; 1269 + /* Skip children who will be reparented to another clock */ 1270 + if (child->new_parent && child->new_parent != clk) 1271 + continue; 1272 + tmp_clk = clk_propagate_rate_change(child, event); 1273 + if (tmp_clk) 1274 + fail_clk = tmp_clk; 1275 + } 1276 + 1277 + /* handle the new child who might not be in clk->children yet */ 1278 + if (clk->new_child) { 1279 + tmp_clk = clk_propagate_rate_change(clk->new_child, event); 1280 + if (tmp_clk) 1281 + fail_clk = tmp_clk; 1299 1282 } 1300 1283 1301 1284 return fail_clk; ··· 1323 1286 1324 1287 old_rate = clk->rate; 1325 1288 1289 + /* set parent */ 1290 + if (clk->new_parent && clk->new_parent != clk->parent) 1291 + __clk_set_parent(clk, clk->new_parent, clk->new_parent_index); 1292 + 1326 1293 if (clk->parent) 1327 1294 best_parent_rate = clk->parent->rate; 1328 1295 ··· 1341 1300 if (clk->notifier_count && old_rate != clk->rate) 1342 1301 __clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate); 1343 1302 1344 - hlist_for_each_entry(child, &clk->children, child_node) 1303 + hlist_for_each_entry(child, &clk->children, child_node) { 1304 + /* Skip children who will be reparented to another clock */ 1305 + if (child->new_parent && child->new_parent != clk) 1306 + continue; 1345 1307 clk_change_rate(child); 1308 + } 1309 + 1310 + /* handle the new child who might not be in clk->children yet */ 1311 + if (clk->new_child) 1312 + clk_change_rate(clk->new_child); 1346 1313 } 1347 1314 1348 1315 /** ··· 1601 1552 1602 1553 /* check that clk_ops are sane. See Documentation/clk.txt */ 1603 1554 if (clk->ops->set_rate && 1604 - !(clk->ops->round_rate && clk->ops->recalc_rate)) { 1605 - pr_warning("%s: %s must implement .round_rate & .recalc_rate\n", 1555 + !((clk->ops->round_rate || clk->ops->determine_rate) && 1556 + clk->ops->recalc_rate)) { 1557 + pr_warning("%s: %s must implement .round_rate or .determine_rate in addition to .recalc_rate\n", 1606 1558 __func__, clk->name); 1607 1559 ret = -EINVAL; 1608 1560 goto out;
+3
include/linux/clk-private.h
··· 33 33 const char **parent_names; 34 34 struct clk **parents; 35 35 u8 num_parents; 36 + u8 new_parent_index; 36 37 unsigned long rate; 37 38 unsigned long new_rate; 39 + struct clk *new_parent; 40 + struct clk *new_child; 38 41 unsigned long flags; 39 42 unsigned int enable_count; 40 43 unsigned int prepare_count;
+7
include/linux/clk-provider.h
··· 79 79 * @round_rate: Given a target rate as input, returns the closest rate actually 80 80 * supported by the clock. 81 81 * 82 + * @determine_rate: Given a target rate as input, returns the closest rate 83 + * actually supported by the clock, and optionally the parent clock 84 + * that should be used to provide the clock rate. 85 + * 82 86 * @get_parent: Queries the hardware to determine the parent of a clock. The 83 87 * return value is a u8 which specifies the index corresponding to 84 88 * the parent clock. This index can be applied to either the ··· 130 126 unsigned long parent_rate); 131 127 long (*round_rate)(struct clk_hw *hw, unsigned long, 132 128 unsigned long *); 129 + long (*determine_rate)(struct clk_hw *hw, unsigned long rate, 130 + unsigned long *best_parent_rate, 131 + struct clk **best_parent_clk); 133 132 int (*set_parent)(struct clk_hw *hw, u8 index); 134 133 u8 (*get_parent)(struct clk_hw *hw); 135 134 int (*set_rate)(struct clk_hw *hw, unsigned long,