aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/clkdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/clkdev.c')
-rw-r--r--drivers/clk/clkdev.c117
1 files changed, 94 insertions, 23 deletions
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 9ab3db8b3988..4cfe39636105 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -52,6 +52,12 @@ struct clk *of_clk_get(struct device_node *np, int index)
52} 52}
53EXPORT_SYMBOL(of_clk_get); 53EXPORT_SYMBOL(of_clk_get);
54 54
55/*
56 * Beware the return values when np is valid, but no clock provider is found.
57 * If name == NULL, the function returns -ENOENT.
58 * If name != NULL, the function returns -EINVAL. This is because __of_clk_get()
59 * is called even if of_property_match_string() returns an error.
60 */
55static struct clk *__of_clk_get_by_name(struct device_node *np, 61static struct clk *__of_clk_get_by_name(struct device_node *np,
56 const char *dev_id, 62 const char *dev_id,
57 const char *name) 63 const char *name)
@@ -401,6 +407,23 @@ static struct clk_lookup *__clk_register_clkdev(struct clk_hw *hw,
401 return cl; 407 return cl;
402} 408}
403 409
410static int do_clk_register_clkdev(struct clk_hw *hw,
411 struct clk_lookup **cl, const char *con_id, const char *dev_id)
412{
413 if (IS_ERR(hw))
414 return PTR_ERR(hw);
415 /*
416 * Since dev_id can be NULL, and NULL is handled specially, we must
417 * pass it as either a NULL format string, or with "%s".
418 */
419 if (dev_id)
420 *cl = __clk_register_clkdev(hw, con_id, "%s", dev_id);
421 else
422 *cl = __clk_register_clkdev(hw, con_id, NULL);
423
424 return *cl ? 0 : -ENOMEM;
425}
426
404/** 427/**
405 * clk_register_clkdev - register one clock lookup for a struct clk 428 * clk_register_clkdev - register one clock lookup for a struct clk
406 * @clk: struct clk to associate with all clk_lookups 429 * @clk: struct clk to associate with all clk_lookups
@@ -423,17 +446,8 @@ int clk_register_clkdev(struct clk *clk, const char *con_id,
423 if (IS_ERR(clk)) 446 if (IS_ERR(clk))
424 return PTR_ERR(clk); 447 return PTR_ERR(clk);
425 448
426 /* 449 return do_clk_register_clkdev(__clk_get_hw(clk), &cl, con_id,
427 * Since dev_id can be NULL, and NULL is handled specially, we must 450 dev_id);
428 * pass it as either a NULL format string, or with "%s".
429 */
430 if (dev_id)
431 cl = __clk_register_clkdev(__clk_get_hw(clk), con_id, "%s",
432 dev_id);
433 else
434 cl = __clk_register_clkdev(__clk_get_hw(clk), con_id, NULL);
435
436 return cl ? 0 : -ENOMEM;
437} 451}
438EXPORT_SYMBOL(clk_register_clkdev); 452EXPORT_SYMBOL(clk_register_clkdev);
439 453
@@ -456,18 +470,75 @@ int clk_hw_register_clkdev(struct clk_hw *hw, const char *con_id,
456{ 470{
457 struct clk_lookup *cl; 471 struct clk_lookup *cl;
458 472
459 if (IS_ERR(hw)) 473 return do_clk_register_clkdev(hw, &cl, con_id, dev_id);
460 return PTR_ERR(hw); 474}
475EXPORT_SYMBOL(clk_hw_register_clkdev);
461 476
462 /* 477static void devm_clkdev_release(struct device *dev, void *res)
463 * Since dev_id can be NULL, and NULL is handled specially, we must 478{
464 * pass it as either a NULL format string, or with "%s". 479 clkdev_drop(*(struct clk_lookup **)res);
465 */ 480}
466 if (dev_id) 481
467 cl = __clk_register_clkdev(hw, con_id, "%s", dev_id); 482static int devm_clk_match_clkdev(struct device *dev, void *res, void *data)
468 else 483{
469 cl = __clk_register_clkdev(hw, con_id, NULL); 484 struct clk_lookup **l = res;
470 485
471 return cl ? 0 : -ENOMEM; 486 return *l == data;
472} 487}
473EXPORT_SYMBOL(clk_hw_register_clkdev); 488
489/**
490 * devm_clk_release_clkdev - Resource managed clkdev lookup release
491 * @dev: device this lookup is bound
492 * @con_id: connection ID string on device
493 * @dev_id: format string describing device name
494 *
495 * Drop the clkdev lookup created with devm_clk_hw_register_clkdev.
496 * Normally this function will not need to be called and the resource
497 * management code will ensure that the resource is freed.
498 */
499void devm_clk_release_clkdev(struct device *dev, const char *con_id,
500 const char *dev_id)
501{
502 struct clk_lookup *cl;
503 int rval;
504
505 cl = clk_find(dev_id, con_id);
506 WARN_ON(!cl);
507 rval = devres_release(dev, devm_clkdev_release,
508 devm_clk_match_clkdev, cl);
509 WARN_ON(rval);
510}
511EXPORT_SYMBOL(devm_clk_release_clkdev);
512
513/**
514 * devm_clk_hw_register_clkdev - managed clk lookup registration for clk_hw
515 * @dev: device this lookup is bound
516 * @hw: struct clk_hw to associate with all clk_lookups
517 * @con_id: connection ID string on device
518 * @dev_id: format string describing device name
519 *
520 * con_id or dev_id may be NULL as a wildcard, just as in the rest of
521 * clkdev.
522 *
523 * To make things easier for mass registration, we detect error clk_hws
524 * from a previous clk_hw_register_*() call, and return the error code for
525 * those. This is to permit this function to be called immediately
526 * after clk_hw_register_*().
527 */
528int devm_clk_hw_register_clkdev(struct device *dev, struct clk_hw *hw,
529 const char *con_id, const char *dev_id)
530{
531 int rval = -ENOMEM;
532 struct clk_lookup **cl;
533
534 cl = devres_alloc(devm_clkdev_release, sizeof(*cl), GFP_KERNEL);
535 if (cl) {
536 rval = do_clk_register_clkdev(hw, cl, con_id, dev_id);
537 if (!rval)
538 devres_add(dev, cl);
539 else
540 devres_free(cl);
541 }
542 return rval;
543}
544EXPORT_SYMBOL(devm_clk_hw_register_clkdev);