aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Hogan <james.hogan@imgtec.com>2013-07-29 07:25:00 -0400
committerMike Turquette <mturquette@linaro.org>2013-08-19 15:27:17 -0400
commit71472c0c06cf9a3d1540762ea205654c584e3bc4 (patch)
tree22db34b3c7bc0d0053fcfac2c95d77adf09107de
parent4935b22c46ea5e2dc44ef0b72db50741649eb3a4 (diff)
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>
-rw-r--r--Documentation/clk.txt46
-rw-r--r--drivers/clk/clk.c142
-rw-r--r--include/linux/clk-private.h3
-rw-r--r--include/linux/clk-provider.h7
4 files changed, 132 insertions, 66 deletions
diff --git a/Documentation/clk.txt b/Documentation/clk.txt
index 6f68ba0d1e01..3aeb5c440442 100644
--- a/Documentation/clk.txt
+++ b/Documentation/clk.txt
@@ -70,6 +70,10 @@ the operations defined in clk.h:
70 unsigned long parent_rate); 70 unsigned long parent_rate);
71 long (*round_rate)(struct clk_hw *hw, unsigned long, 71 long (*round_rate)(struct clk_hw *hw, unsigned long,
72 unsigned long *); 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 int (*set_parent)(struct clk_hw *hw, u8 index); 77 int (*set_parent)(struct clk_hw *hw, u8 index);
74 u8 (*get_parent)(struct clk_hw *hw); 78 u8 (*get_parent)(struct clk_hw *hw);
75 int (*set_rate)(struct clk_hw *hw, unsigned long); 79 int (*set_rate)(struct clk_hw *hw, unsigned long);
@@ -179,26 +183,28 @@ mandatory, a cell marked as "n" implies that either including that
179callback is invalid or otherwise unnecessary. Empty cells are either 183callback is invalid or otherwise unnecessary. Empty cells are either
180optional or must be evaluated on a case-by-case basis. 184optional or must be evaluated on a case-by-case basis.
181 185
182 clock hardware characteristics 186 clock hardware characteristics
183 ----------------------------------------------------------- 187 -----------------------------------------------------------
184 | gate | change rate | single parent | multiplexer | root | 188 | gate | change rate | single parent | multiplexer | root |
185 |------|-------------|---------------|-------------|------| 189 |------|-------------|---------------|-------------|------|
186.prepare | | | | | | 190.prepare | | | | | |
187.unprepare | | | | | | 191.unprepare | | | | | |
188 | | | | | | 192 | | | | | |
189.enable | y | | | | | 193.enable | y | | | | |
190.disable | y | | | | | 194.disable | y | | | | |
191.is_enabled | y | | | | | 195.is_enabled | y | | | | |
192 | | | | | | 196 | | | | | |
193.recalc_rate | | y | | | | 197.recalc_rate | | y | | | |
194.round_rate | | y | | | | 198.round_rate | | y [1] | | | |
195.set_rate | | y | | | | 199.determine_rate | | y [1] | | | |
196 | | | | | | 200.set_rate | | y | | | |
197.set_parent | | | n | y | n | 201 | | | | | |
198.get_parent | | | n | y | n | 202.set_parent | | | n | y | n |
199 | | | | | | 203.get_parent | | | n | y | n |
200.init | | | | | | 204 | | | | | |
201 ----------------------------------------------------------- 205.init | | | | | |
206 -----------------------------------------------------------
207[1] either one of round_rate or determine_rate is required.
202 208
203Finally, register your clock at run-time with a hardware-specific 209Finally, register your clock at run-time with a hardware-specific
204registration function. This function simply populates struct clk_foo's 210registration function. This function simply populates struct clk_foo's
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 3d57cf64c9e7..f33f1ccf1b2f 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -889,21 +889,24 @@ EXPORT_SYMBOL_GPL(clk_enable);
889unsigned long __clk_round_rate(struct clk *clk, unsigned long rate) 889unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
890{ 890{
891 unsigned long parent_rate = 0; 891 unsigned long parent_rate = 0;
892 struct clk *parent;
892 893
893 if (!clk) 894 if (!clk)
894 return 0; 895 return 0;
895 896
896 if (!clk->ops->round_rate) { 897 parent = clk->parent;
897 if (clk->flags & CLK_SET_RATE_PARENT) 898 if (parent)
898 return __clk_round_rate(clk->parent, rate); 899 parent_rate = parent->rate;
899 else 900
900 return clk->rate; 901 if (clk->ops->determine_rate)
901 } 902 return clk->ops->determine_rate(clk->hw, rate, &parent_rate,
902 903 &parent);
903 if (clk->parent) 904 else if (clk->ops->round_rate)
904 parent_rate = clk->parent->rate; 905 return clk->ops->round_rate(clk->hw, rate, &parent_rate);
905 906 else if (clk->flags & CLK_SET_RATE_PARENT)
906 return clk->ops->round_rate(clk->hw, rate, &parent_rate); 907 return __clk_round_rate(clk->parent, rate);
908 else
909 return clk->rate;
907} 910}
908 911
909/** 912/**
@@ -1056,6 +1059,10 @@ static u8 clk_fetch_parent_index(struct clk *clk, struct clk *parent)
1056 1059
1057static void clk_reparent(struct clk *clk, struct clk *new_parent) 1060static void clk_reparent(struct clk *clk, struct clk *new_parent)
1058{ 1061{
1062 /* avoid duplicate POST_RATE_CHANGE notifications */
1063 if (new_parent->new_child == clk)
1064 new_parent->new_child = NULL;
1065
1059 hlist_del(&clk->child_node); 1066 hlist_del(&clk->child_node);
1060 1067
1061 if (new_parent) 1068 if (new_parent)
@@ -1176,18 +1183,25 @@ out:
1176 return ret; 1183 return ret;
1177} 1184}
1178 1185
1179static void clk_calc_subtree(struct clk *clk, unsigned long new_rate) 1186static void clk_calc_subtree(struct clk *clk, unsigned long new_rate,
1187 struct clk *new_parent, u8 p_index)
1180{ 1188{
1181 struct clk *child; 1189 struct clk *child;
1182 1190
1183 clk->new_rate = new_rate; 1191 clk->new_rate = new_rate;
1192 clk->new_parent = new_parent;
1193 clk->new_parent_index = p_index;
1194 /* include clk in new parent's PRE_RATE_CHANGE notifications */
1195 clk->new_child = NULL;
1196 if (new_parent && new_parent != clk->parent)
1197 new_parent->new_child = clk;
1184 1198
1185 hlist_for_each_entry(child, &clk->children, child_node) { 1199 hlist_for_each_entry(child, &clk->children, child_node) {
1186 if (child->ops->recalc_rate) 1200 if (child->ops->recalc_rate)
1187 child->new_rate = child->ops->recalc_rate(child->hw, new_rate); 1201 child->new_rate = child->ops->recalc_rate(child->hw, new_rate);
1188 else 1202 else
1189 child->new_rate = new_rate; 1203 child->new_rate = new_rate;
1190 clk_calc_subtree(child, child->new_rate); 1204 clk_calc_subtree(child, child->new_rate, NULL, 0);
1191 } 1205 }
1192} 1206}
1193 1207
@@ -1198,50 +1212,63 @@ static void clk_calc_subtree(struct clk *clk, unsigned long new_rate)
1198static struct clk *clk_calc_new_rates(struct clk *clk, unsigned long rate) 1212static struct clk *clk_calc_new_rates(struct clk *clk, unsigned long rate)
1199{ 1213{
1200 struct clk *top = clk; 1214 struct clk *top = clk;
1215 struct clk *old_parent, *parent;
1201 unsigned long best_parent_rate = 0; 1216 unsigned long best_parent_rate = 0;
1202 unsigned long new_rate; 1217 unsigned long new_rate;
1218 u8 p_index = 0;
1203 1219
1204 /* sanity */ 1220 /* sanity */
1205 if (IS_ERR_OR_NULL(clk)) 1221 if (IS_ERR_OR_NULL(clk))
1206 return NULL; 1222 return NULL;
1207 1223
1208 /* save parent rate, if it exists */ 1224 /* save parent rate, if it exists */
1209 if (clk->parent) 1225 parent = old_parent = clk->parent;
1210 best_parent_rate = clk->parent->rate; 1226 if (parent)
1211 1227 best_parent_rate = parent->rate;
1212 /* never propagate up to the parent */ 1228
1213 if (!(clk->flags & CLK_SET_RATE_PARENT)) { 1229 /* find the closest rate and parent clk/rate */
1214 if (!clk->ops->round_rate) { 1230 if (clk->ops->determine_rate) {
1215 clk->new_rate = clk->rate; 1231 new_rate = clk->ops->determine_rate(clk->hw, rate,
1216 return NULL; 1232 &best_parent_rate,
1217 } 1233 &parent);
1218 new_rate = clk->ops->round_rate(clk->hw, rate, &best_parent_rate); 1234 } else if (clk->ops->round_rate) {
1235 new_rate = clk->ops->round_rate(clk->hw, rate,
1236 &best_parent_rate);
1237 } else if (!parent || !(clk->flags & CLK_SET_RATE_PARENT)) {
1238 /* pass-through clock without adjustable parent */
1239 clk->new_rate = clk->rate;
1240 return NULL;
1241 } else {
1242 /* pass-through clock with adjustable parent */
1243 top = clk_calc_new_rates(parent, rate);
1244 new_rate = parent->new_rate;
1219 goto out; 1245 goto out;
1220 } 1246 }
1221 1247
1222 /* need clk->parent from here on out */ 1248 /* some clocks must be gated to change parent */
1223 if (!clk->parent) { 1249 if (parent != old_parent &&
1224 pr_debug("%s: %s has NULL parent\n", __func__, clk->name); 1250 (clk->flags & CLK_SET_PARENT_GATE) && clk->prepare_count) {
1251 pr_debug("%s: %s not gated but wants to reparent\n",
1252 __func__, clk->name);
1225 return NULL; 1253 return NULL;
1226 } 1254 }
1227 1255
1228 if (!clk->ops->round_rate) { 1256 /* try finding the new parent index */
1229 top = clk_calc_new_rates(clk->parent, rate); 1257 if (parent) {
1230 new_rate = clk->parent->new_rate; 1258 p_index = clk_fetch_parent_index(clk, parent);
1231 1259 if (p_index == clk->num_parents) {
1232 goto out; 1260 pr_debug("%s: clk %s can not be parent of clk %s\n",
1261 __func__, parent->name, clk->name);
1262 return NULL;
1263 }
1233 } 1264 }
1234 1265
1235 new_rate = clk->ops->round_rate(clk->hw, rate, &best_parent_rate); 1266 if ((clk->flags & CLK_SET_RATE_PARENT) && parent &&
1236 1267 best_parent_rate != parent->rate)
1237 if (best_parent_rate != clk->parent->rate) { 1268 top = clk_calc_new_rates(parent, best_parent_rate);
1238 top = clk_calc_new_rates(clk->parent, best_parent_rate);
1239
1240 goto out;
1241 }
1242 1269
1243out: 1270out:
1244 clk_calc_subtree(clk, new_rate); 1271 clk_calc_subtree(clk, new_rate, parent, p_index);
1245 1272
1246 return top; 1273 return top;
1247} 1274}
@@ -1253,7 +1280,7 @@ out:
1253 */ 1280 */
1254static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long event) 1281static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long event)
1255{ 1282{
1256 struct clk *child, *fail_clk = NULL; 1283 struct clk *child, *tmp_clk, *fail_clk = NULL;
1257 int ret = NOTIFY_DONE; 1284 int ret = NOTIFY_DONE;
1258 1285
1259 if (clk->rate == clk->new_rate) 1286 if (clk->rate == clk->new_rate)
@@ -1266,9 +1293,19 @@ static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long even
1266 } 1293 }
1267 1294
1268 hlist_for_each_entry(child, &clk->children, child_node) { 1295 hlist_for_each_entry(child, &clk->children, child_node) {
1269 clk = clk_propagate_rate_change(child, event); 1296 /* Skip children who will be reparented to another clock */
1270 if (clk) 1297 if (child->new_parent && child->new_parent != clk)
1271 fail_clk = clk; 1298 continue;
1299 tmp_clk = clk_propagate_rate_change(child, event);
1300 if (tmp_clk)
1301 fail_clk = tmp_clk;
1302 }
1303
1304 /* handle the new child who might not be in clk->children yet */
1305 if (clk->new_child) {
1306 tmp_clk = clk_propagate_rate_change(clk->new_child, event);
1307 if (tmp_clk)
1308 fail_clk = tmp_clk;
1272 } 1309 }
1273 1310
1274 return fail_clk; 1311 return fail_clk;
@@ -1286,6 +1323,10 @@ static void clk_change_rate(struct clk *clk)
1286 1323
1287 old_rate = clk->rate; 1324 old_rate = clk->rate;
1288 1325
1326 /* set parent */
1327 if (clk->new_parent && clk->new_parent != clk->parent)
1328 __clk_set_parent(clk, clk->new_parent, clk->new_parent_index);
1329
1289 if (clk->parent) 1330 if (clk->parent)
1290 best_parent_rate = clk->parent->rate; 1331 best_parent_rate = clk->parent->rate;
1291 1332
@@ -1300,8 +1341,16 @@ static void clk_change_rate(struct clk *clk)
1300 if (clk->notifier_count && old_rate != clk->rate) 1341 if (clk->notifier_count && old_rate != clk->rate)
1301 __clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate); 1342 __clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate);
1302 1343
1303 hlist_for_each_entry(child, &clk->children, child_node) 1344 hlist_for_each_entry(child, &clk->children, child_node) {
1345 /* Skip children who will be reparented to another clock */
1346 if (child->new_parent && child->new_parent != clk)
1347 continue;
1304 clk_change_rate(child); 1348 clk_change_rate(child);
1349 }
1350
1351 /* handle the new child who might not be in clk->children yet */
1352 if (clk->new_child)
1353 clk_change_rate(clk->new_child);
1305} 1354}
1306 1355
1307/** 1356/**
@@ -1552,8 +1601,9 @@ int __clk_init(struct device *dev, struct clk *clk)
1552 1601
1553 /* check that clk_ops are sane. See Documentation/clk.txt */ 1602 /* check that clk_ops are sane. See Documentation/clk.txt */
1554 if (clk->ops->set_rate && 1603 if (clk->ops->set_rate &&
1555 !(clk->ops->round_rate && clk->ops->recalc_rate)) { 1604 !((clk->ops->round_rate || clk->ops->determine_rate) &&
1556 pr_warning("%s: %s must implement .round_rate & .recalc_rate\n", 1605 clk->ops->recalc_rate)) {
1606 pr_warning("%s: %s must implement .round_rate or .determine_rate in addition to .recalc_rate\n",
1557 __func__, clk->name); 1607 __func__, clk->name);
1558 ret = -EINVAL; 1608 ret = -EINVAL;
1559 goto out; 1609 goto out;
diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
index dd7adff76e81..8138c94409f3 100644
--- a/include/linux/clk-private.h
+++ b/include/linux/clk-private.h
@@ -33,8 +33,11 @@ struct clk {
33 const char **parent_names; 33 const char **parent_names;
34 struct clk **parents; 34 struct clk **parents;
35 u8 num_parents; 35 u8 num_parents;
36 u8 new_parent_index;
36 unsigned long rate; 37 unsigned long rate;
37 unsigned long new_rate; 38 unsigned long new_rate;
39 struct clk *new_parent;
40 struct clk *new_child;
38 unsigned long flags; 41 unsigned long flags;
39 unsigned int enable_count; 42 unsigned int enable_count;
40 unsigned int prepare_count; 43 unsigned int prepare_count;
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index a83409285a7f..4f525b37c6fd 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -79,6 +79,10 @@ struct clk_hw;
79 * @round_rate: Given a target rate as input, returns the closest rate actually 79 * @round_rate: Given a target rate as input, returns the closest rate actually
80 * supported by the clock. 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 * @get_parent: Queries the hardware to determine the parent of a clock. The 86 * @get_parent: Queries the hardware to determine the parent of a clock. The
83 * return value is a u8 which specifies the index corresponding to 87 * return value is a u8 which specifies the index corresponding to
84 * the parent clock. This index can be applied to either the 88 * the parent clock. This index can be applied to either the
@@ -126,6 +130,9 @@ struct clk_ops {
126 unsigned long parent_rate); 130 unsigned long parent_rate);
127 long (*round_rate)(struct clk_hw *hw, unsigned long, 131 long (*round_rate)(struct clk_hw *hw, unsigned long,
128 unsigned long *); 132 unsigned long *);
133 long (*determine_rate)(struct clk_hw *hw, unsigned long rate,
134 unsigned long *best_parent_rate,
135 struct clk **best_parent_clk);
129 int (*set_parent)(struct clk_hw *hw, u8 index); 136 int (*set_parent)(struct clk_hw *hw, u8 index);
130 u8 (*get_parent)(struct clk_hw *hw); 137 u8 (*get_parent)(struct clk_hw *hw);
131 int (*set_rate)(struct clk_hw *hw, unsigned long, 138 int (*set_rate)(struct clk_hw *hw, unsigned long,