summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatti Vaittinen <matti.vaittinen@fi.rohmeurope.com>2018-12-07 06:09:39 -0500
committerStephen Boyd <sboyd@kernel.org>2019-02-06 13:35:02 -0500
commit3eee6c7d119cd8563ad25898f94d6c1b514da548 (patch)
treea78d21a7c0f1ba47021cec1f0730f14036568166
parentbfeffd155283772bbe78c6a05dec7c0128ee500c (diff)
clkdev: add managed clkdev lookup registration
Clkdev registration lacks of managed registration functions and it seems few drivers do not drop clkdev lookups at exit. Add devm_clk_hw_register_clkdev and devm_clk_release_clkdev to ease lookup releasing at exit. Signed-off-by: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com> Signed-off-by: Stephen Boyd <sboyd@kernel.org>
-rw-r--r--Documentation/driver-model/devres.txt1
-rw-r--r--drivers/clk/clkdev.c111
-rw-r--r--include/linux/clkdev.h4
3 files changed, 93 insertions, 23 deletions
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
index b277cafce71e..805b7bf5d98f 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -245,6 +245,7 @@ CLOCK
245 devm_clk_put() 245 devm_clk_put()
246 devm_clk_hw_register() 246 devm_clk_hw_register()
247 devm_of_clk_add_hw_provider() 247 devm_of_clk_add_hw_provider()
248 devm_clk_hw_register_clkdev()
248 249
249DMA 250DMA
250 dmaenginem_async_device_register() 251 dmaenginem_async_device_register()
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 9ab3db8b3988..4621f8a91fc0 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -401,6 +401,23 @@ static struct clk_lookup *__clk_register_clkdev(struct clk_hw *hw,
401 return cl; 401 return cl;
402} 402}
403 403
404static int do_clk_register_clkdev(struct clk_hw *hw,
405 struct clk_lookup **cl, const char *con_id, const char *dev_id)
406{
407 if (IS_ERR(hw))
408 return PTR_ERR(hw);
409 /*
410 * Since dev_id can be NULL, and NULL is handled specially, we must
411 * pass it as either a NULL format string, or with "%s".
412 */
413 if (dev_id)
414 *cl = __clk_register_clkdev(hw, con_id, "%s", dev_id);
415 else
416 *cl = __clk_register_clkdev(hw, con_id, NULL);
417
418 return *cl ? 0 : -ENOMEM;
419}
420
404/** 421/**
405 * clk_register_clkdev - register one clock lookup for a struct clk 422 * clk_register_clkdev - register one clock lookup for a struct clk
406 * @clk: struct clk to associate with all clk_lookups 423 * @clk: struct clk to associate with all clk_lookups
@@ -423,17 +440,8 @@ int clk_register_clkdev(struct clk *clk, const char *con_id,
423 if (IS_ERR(clk)) 440 if (IS_ERR(clk))
424 return PTR_ERR(clk); 441 return PTR_ERR(clk);
425 442
426 /* 443 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 444 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} 445}
438EXPORT_SYMBOL(clk_register_clkdev); 446EXPORT_SYMBOL(clk_register_clkdev);
439 447
@@ -456,18 +464,75 @@ int clk_hw_register_clkdev(struct clk_hw *hw, const char *con_id,
456{ 464{
457 struct clk_lookup *cl; 465 struct clk_lookup *cl;
458 466
459 if (IS_ERR(hw)) 467 return do_clk_register_clkdev(hw, &cl, con_id, dev_id);
460 return PTR_ERR(hw); 468}
469EXPORT_SYMBOL(clk_hw_register_clkdev);
461 470
462 /* 471static void devm_clkdev_release(struct device *dev, void *res)
463 * Since dev_id can be NULL, and NULL is handled specially, we must 472{
464 * pass it as either a NULL format string, or with "%s". 473 clkdev_drop(*(struct clk_lookup **)res);
465 */ 474}
466 if (dev_id)
467 cl = __clk_register_clkdev(hw, con_id, "%s", dev_id);
468 else
469 cl = __clk_register_clkdev(hw, con_id, NULL);
470 475
471 return cl ? 0 : -ENOMEM; 476static int devm_clk_match_clkdev(struct device *dev, void *res, void *data)
477{
478 struct clk_lookup **l = res;
479
480 return *l == data;
472} 481}
473EXPORT_SYMBOL(clk_hw_register_clkdev); 482
483/**
484 * devm_clk_release_clkdev - Resource managed clkdev lookup release
485 * @dev: device this lookup is bound
486 * @con_id: connection ID string on device
487 * @dev_id: format string describing device name
488 *
489 * Drop the clkdev lookup created with devm_clk_hw_register_clkdev.
490 * Normally this function will not need to be called and the resource
491 * management code will ensure that the resource is freed.
492 */
493void devm_clk_release_clkdev(struct device *dev, const char *con_id,
494 const char *dev_id)
495{
496 struct clk_lookup *cl;
497 int rval;
498
499 cl = clk_find(dev_id, con_id);
500 WARN_ON(!cl);
501 rval = devres_release(dev, devm_clkdev_release,
502 devm_clk_match_clkdev, cl);
503 WARN_ON(rval);
504}
505EXPORT_SYMBOL(devm_clk_release_clkdev);
506
507/**
508 * devm_clk_hw_register_clkdev - managed clk lookup registration for clk_hw
509 * @dev: device this lookup is bound
510 * @hw: struct clk_hw to associate with all clk_lookups
511 * @con_id: connection ID string on device
512 * @dev_id: format string describing device name
513 *
514 * con_id or dev_id may be NULL as a wildcard, just as in the rest of
515 * clkdev.
516 *
517 * To make things easier for mass registration, we detect error clk_hws
518 * from a previous clk_hw_register_*() call, and return the error code for
519 * those. This is to permit this function to be called immediately
520 * after clk_hw_register_*().
521 */
522int devm_clk_hw_register_clkdev(struct device *dev, struct clk_hw *hw,
523 const char *con_id, const char *dev_id)
524{
525 int rval = -ENOMEM;
526 struct clk_lookup **cl;
527
528 cl = devres_alloc(devm_clkdev_release, sizeof(*cl), GFP_KERNEL);
529 if (cl) {
530 rval = do_clk_register_clkdev(hw, cl, con_id, dev_id);
531 if (!rval)
532 devres_add(dev, cl);
533 else
534 devres_free(cl);
535 }
536 return rval;
537}
538EXPORT_SYMBOL(devm_clk_hw_register_clkdev);
diff --git a/include/linux/clkdev.h b/include/linux/clkdev.h
index 4890ff033220..ccb32af5848b 100644
--- a/include/linux/clkdev.h
+++ b/include/linux/clkdev.h
@@ -52,4 +52,8 @@ int clk_add_alias(const char *, const char *, const char *, struct device *);
52int clk_register_clkdev(struct clk *, const char *, const char *); 52int clk_register_clkdev(struct clk *, const char *, const char *);
53int clk_hw_register_clkdev(struct clk_hw *, const char *, const char *); 53int clk_hw_register_clkdev(struct clk_hw *, const char *, const char *);
54 54
55int devm_clk_hw_register_clkdev(struct device *dev, struct clk_hw *hw,
56 const char *con_id, const char *dev_id);
57void devm_clk_release_clkdev(struct device *dev, const char *con_id,
58 const char *dev_id);
55#endif 59#endif