aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk
diff options
context:
space:
mode:
authorMike Turquette <mturquette@linaro.org>2012-03-29 17:30:40 -0400
committerMike Turquette <mturquette@linaro.org>2012-04-24 19:37:39 -0400
commitd1302a36a7f1c33d1a8babc6a510e1401a5e5aed (patch)
treebcb0d5f659a762764b75720fdada09ac9c548886 /drivers/clk
parentd305fb78f31209596c9135d396a0d3af7ac86947 (diff)
clk: core: copy parent_names & return error codes
This patch cleans up clk_register and solves a few bugs by teaching clk_register and __clk_init to return error codes (instead of just NULL) to better align with the existing clk.h api. Along with that change this patch also introduces a new behavior whereby clk_register copies the parent_names array, thus allowing platforms to declare their parent_names arrays as __initdata. Signed-off-by: Mike Turquette <mturquette@linaro.org>
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/clk.c65
1 files changed, 53 insertions, 12 deletions
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index ddade8759ea9..8f7c3849c8f6 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1185,34 +1185,41 @@ EXPORT_SYMBOL_GPL(clk_set_parent);
1185 * very large numbers of clocks that need to be statically initialized. It is 1185 * very large numbers of clocks that need to be statically initialized. It is
1186 * a layering violation to include clk-private.h from any code which implements 1186 * a layering violation to include clk-private.h from any code which implements
1187 * a clock's .ops; as such any statically initialized clock data MUST be in a 1187 * a clock's .ops; as such any statically initialized clock data MUST be in a
1188 * separate C file from the logic that implements it's operations. 1188 * separate C file from the logic that implements it's operations. Returns 0
1189 * on success, otherwise an error code.
1189 */ 1190 */
1190void __clk_init(struct device *dev, struct clk *clk) 1191int __clk_init(struct device *dev, struct clk *clk)
1191{ 1192{
1192 int i; 1193 int i, ret = 0;
1193 struct clk *orphan; 1194 struct clk *orphan;
1194 struct hlist_node *tmp, *tmp2; 1195 struct hlist_node *tmp, *tmp2;
1195 1196
1196 if (!clk) 1197 if (!clk)
1197 return; 1198 return -EINVAL;
1198 1199
1199 mutex_lock(&prepare_lock); 1200 mutex_lock(&prepare_lock);
1200 1201
1201 /* check to see if a clock with this name is already registered */ 1202 /* check to see if a clock with this name is already registered */
1202 if (__clk_lookup(clk->name)) 1203 if (__clk_lookup(clk->name)) {
1204 pr_debug("%s: clk %s already initialized\n",
1205 __func__, clk->name);
1206 ret = -EEXIST;
1203 goto out; 1207 goto out;
1208 }
1204 1209
1205 /* check that clk_ops are sane. See Documentation/clk.txt */ 1210 /* check that clk_ops are sane. See Documentation/clk.txt */
1206 if (clk->ops->set_rate && 1211 if (clk->ops->set_rate &&
1207 !(clk->ops->round_rate && clk->ops->recalc_rate)) { 1212 !(clk->ops->round_rate && clk->ops->recalc_rate)) {
1208 pr_warning("%s: %s must implement .round_rate & .recalc_rate\n", 1213 pr_warning("%s: %s must implement .round_rate & .recalc_rate\n",
1209 __func__, clk->name); 1214 __func__, clk->name);
1215 ret = -EINVAL;
1210 goto out; 1216 goto out;
1211 } 1217 }
1212 1218
1213 if (clk->ops->set_parent && !clk->ops->get_parent) { 1219 if (clk->ops->set_parent && !clk->ops->get_parent) {
1214 pr_warning("%s: %s must implement .get_parent & .set_parent\n", 1220 pr_warning("%s: %s must implement .get_parent & .set_parent\n",
1215 __func__, clk->name); 1221 __func__, clk->name);
1222 ret = -EINVAL;
1216 goto out; 1223 goto out;
1217 } 1224 }
1218 1225
@@ -1308,7 +1315,7 @@ void __clk_init(struct device *dev, struct clk *clk)
1308out: 1315out:
1309 mutex_unlock(&prepare_lock); 1316 mutex_unlock(&prepare_lock);
1310 1317
1311 return; 1318 return ret;
1312} 1319}
1313 1320
1314/** 1321/**
@@ -1324,29 +1331,63 @@ out:
1324 * clk_register is the primary interface for populating the clock tree with new 1331 * clk_register is the primary interface for populating the clock tree with new
1325 * clock nodes. It returns a pointer to the newly allocated struct clk which 1332 * clock nodes. It returns a pointer to the newly allocated struct clk which
1326 * cannot be dereferenced by driver code but may be used in conjuction with the 1333 * cannot be dereferenced by driver code but may be used in conjuction with the
1327 * rest of the clock API. 1334 * rest of the clock API. In the event of an error clk_register will return an
1335 * error code; drivers must test for an error code after calling clk_register.
1328 */ 1336 */
1329struct clk *clk_register(struct device *dev, const char *name, 1337struct clk *clk_register(struct device *dev, const char *name,
1330 const struct clk_ops *ops, struct clk_hw *hw, 1338 const struct clk_ops *ops, struct clk_hw *hw,
1331 const char **parent_names, u8 num_parents, unsigned long flags) 1339 const char **parent_names, u8 num_parents, unsigned long flags)
1332{ 1340{
1341 int i, ret;
1333 struct clk *clk; 1342 struct clk *clk;
1334 1343
1335 clk = kzalloc(sizeof(*clk), GFP_KERNEL); 1344 clk = kzalloc(sizeof(*clk), GFP_KERNEL);
1336 if (!clk) 1345 if (!clk) {
1337 return NULL; 1346 pr_err("%s: could not allocate clk\n", __func__);
1347 ret = -ENOMEM;
1348 goto fail_out;
1349 }
1338 1350
1339 clk->name = name; 1351 clk->name = name;
1340 clk->ops = ops; 1352 clk->ops = ops;
1341 clk->hw = hw; 1353 clk->hw = hw;
1342 clk->flags = flags; 1354 clk->flags = flags;
1343 clk->parent_names = parent_names;
1344 clk->num_parents = num_parents; 1355 clk->num_parents = num_parents;
1345 hw->clk = clk; 1356 hw->clk = clk;
1346 1357
1347 __clk_init(dev, clk); 1358 /* allocate local copy in case parent_names is __initdata */
1359 clk->parent_names = kzalloc((sizeof(char*) * num_parents),
1360 GFP_KERNEL);
1361
1362 if (!clk->parent_names) {
1363 pr_err("%s: could not allocate clk->parent_names\n", __func__);
1364 ret = -ENOMEM;
1365 goto fail_parent_names;
1366 }
1367
1368
1369 /* copy each string name in case parent_names is __initdata */
1370 for (i = 0; i < num_parents; i++) {
1371 clk->parent_names[i] = kstrdup(parent_names[i], GFP_KERNEL);
1372 if (!clk->parent_names[i]) {
1373 pr_err("%s: could not copy parent_names\n", __func__);
1374 ret = -ENOMEM;
1375 goto fail_parent_names_copy;
1376 }
1377 }
1378
1379 ret = __clk_init(dev, clk);
1380 if (!ret)
1381 return clk;
1348 1382
1349 return clk; 1383fail_parent_names_copy:
1384 while (--i >= 0)
1385 kfree(clk->parent_names[i]);
1386 kfree(clk->parent_names);
1387fail_parent_names:
1388 kfree(clk);
1389fail_out:
1390 return ERR_PTR(ret);
1350} 1391}
1351EXPORT_SYMBOL_GPL(clk_register); 1392EXPORT_SYMBOL_GPL(clk_register);
1352 1393