diff options
-rw-r--r-- | Documentation/clk.txt | 46 | ||||
-rw-r--r-- | drivers/clk/clk.c | 142 | ||||
-rw-r--r-- | include/linux/clk-private.h | 3 | ||||
-rw-r--r-- | include/linux/clk-provider.h | 7 |
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 | |||
179 | callback is invalid or otherwise unnecessary. Empty cells are either | 183 | callback is invalid or otherwise unnecessary. Empty cells are either |
180 | optional or must be evaluated on a case-by-case basis. | 184 | optional 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 | ||
203 | Finally, register your clock at run-time with a hardware-specific | 209 | Finally, register your clock at run-time with a hardware-specific |
204 | registration function. This function simply populates struct clk_foo's | 210 | registration 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); | |||
889 | unsigned long __clk_round_rate(struct clk *clk, unsigned long rate) | 889 | unsigned 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 | ||
1057 | static void clk_reparent(struct clk *clk, struct clk *new_parent) | 1060 | static 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 | ||
1179 | static void clk_calc_subtree(struct clk *clk, unsigned long new_rate) | 1186 | static 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) | |||
1198 | static struct clk *clk_calc_new_rates(struct clk *clk, unsigned long rate) | 1212 | static 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 | ||
1243 | out: | 1270 | out: |
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 | */ |
1254 | static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long event) | 1281 | static 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, |