aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/reset
diff options
context:
space:
mode:
authorPhilipp Zabel <p.zabel@pengutronix.de>2019-02-21 10:25:53 -0500
committerPhilipp Zabel <p.zabel@pengutronix.de>2019-03-20 06:16:55 -0400
commitc84b0326d5e4fe08d493f6fff245da2ad473f4ae (patch)
treeaa1f13278664569396e621650b10fe67d30cc551 /drivers/reset
parent9e98c678c2d6ae3a17cb2de55d17f69dddaa231b (diff)
reset: add acquired/released state for exclusive reset controls
There are cases where a driver needs explicit control over a reset line that is exclusively conneted to its device, but this control has to be temporarily handed over to the power domain controller to handle reset requirements during power transitions. Allow multiple exclusive reset controls to be requested in 'released' state for the same physical reset line, only one of which can be acquired at the same time. Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de> Signed-off-by: Thierry Reding <treding@nvidia.com>
Diffstat (limited to 'drivers/reset')
-rw-r--r--drivers/reset/core.c139
1 files changed, 127 insertions, 12 deletions
diff --git a/drivers/reset/core.c b/drivers/reset/core.c
index 9582efb70025..1e8a42b16f23 100644
--- a/drivers/reset/core.c
+++ b/drivers/reset/core.c
@@ -34,6 +34,7 @@ static LIST_HEAD(reset_lookup_list);
34 * @id: ID of the reset controller in the reset 34 * @id: ID of the reset controller in the reset
35 * controller device 35 * controller device
36 * @refcnt: Number of gets of this reset_control 36 * @refcnt: Number of gets of this reset_control
37 * @acquired: Only one reset_control may be acquired for a given rcdev and id.
37 * @shared: Is this a shared (1), or an exclusive (0) reset_control? 38 * @shared: Is this a shared (1), or an exclusive (0) reset_control?
38 * @deassert_cnt: Number of times this reset line has been deasserted 39 * @deassert_cnt: Number of times this reset line has been deasserted
39 * @triggered_count: Number of times this reset line has been reset. Currently 40 * @triggered_count: Number of times this reset line has been reset. Currently
@@ -45,6 +46,7 @@ struct reset_control {
45 struct list_head list; 46 struct list_head list;
46 unsigned int id; 47 unsigned int id;
47 struct kref refcnt; 48 struct kref refcnt;
49 bool acquired;
48 bool shared; 50 bool shared;
49 bool array; 51 bool array;
50 atomic_t deassert_count; 52 atomic_t deassert_count;
@@ -63,6 +65,17 @@ struct reset_control_array {
63 struct reset_control *rstc[]; 65 struct reset_control *rstc[];
64}; 66};
65 67
68static const char *rcdev_name(struct reset_controller_dev *rcdev)
69{
70 if (rcdev->dev)
71 return dev_name(rcdev->dev);
72
73 if (rcdev->of_node)
74 return rcdev->of_node->full_name;
75
76 return NULL;
77}
78
66/** 79/**
67 * of_reset_simple_xlate - translate reset_spec to the reset line number 80 * of_reset_simple_xlate - translate reset_spec to the reset line number
68 * @rcdev: a pointer to the reset controller device 81 * @rcdev: a pointer to the reset controller device
@@ -272,6 +285,9 @@ int reset_control_reset(struct reset_control *rstc)
272 285
273 if (atomic_inc_return(&rstc->triggered_count) != 1) 286 if (atomic_inc_return(&rstc->triggered_count) != 1)
274 return 0; 287 return 0;
288 } else {
289 if (!rstc->acquired)
290 return -EPERM;
275 } 291 }
276 292
277 ret = rstc->rcdev->ops->reset(rstc->rcdev, rstc->id); 293 ret = rstc->rcdev->ops->reset(rstc->rcdev, rstc->id);
@@ -334,6 +350,12 @@ int reset_control_assert(struct reset_control *rstc)
334 */ 350 */
335 if (!rstc->rcdev->ops->assert) 351 if (!rstc->rcdev->ops->assert)
336 return -ENOTSUPP; 352 return -ENOTSUPP;
353
354 if (!rstc->acquired) {
355 WARN(1, "reset %s (ID: %u) is not acquired\n",
356 rcdev_name(rstc->rcdev), rstc->id);
357 return -EPERM;
358 }
337 } 359 }
338 360
339 return rstc->rcdev->ops->assert(rstc->rcdev, rstc->id); 361 return rstc->rcdev->ops->assert(rstc->rcdev, rstc->id);
@@ -369,6 +391,12 @@ int reset_control_deassert(struct reset_control *rstc)
369 391
370 if (atomic_inc_return(&rstc->deassert_count) != 1) 392 if (atomic_inc_return(&rstc->deassert_count) != 1)
371 return 0; 393 return 0;
394 } else {
395 if (!rstc->acquired) {
396 WARN(1, "reset %s (ID: %u) is not acquired\n",
397 rcdev_name(rstc->rcdev), rstc->id);
398 return -EPERM;
399 }
372 } 400 }
373 401
374 /* 402 /*
@@ -406,9 +434,81 @@ int reset_control_status(struct reset_control *rstc)
406} 434}
407EXPORT_SYMBOL_GPL(reset_control_status); 435EXPORT_SYMBOL_GPL(reset_control_status);
408 436
437/**
438 * reset_control_acquire() - acquires a reset control for exclusive use
439 * @rstc: reset control
440 *
441 * This is used to explicitly acquire a reset control for exclusive use. Note
442 * that exclusive resets are requested as acquired by default. In order for a
443 * second consumer to be able to control the reset, the first consumer has to
444 * release it first. Typically the easiest way to achieve this is to call the
445 * reset_control_get_exclusive_released() to obtain an instance of the reset
446 * control. Such reset controls are not acquired by default.
447 *
448 * Consumers implementing shared access to an exclusive reset need to follow
449 * a specific protocol in order to work together. Before consumers can change
450 * a reset they must acquire exclusive access using reset_control_acquire().
451 * After they are done operating the reset, they must release exclusive access
452 * with a call to reset_control_release(). Consumers are not granted exclusive
453 * access to the reset as long as another consumer hasn't released a reset.
454 *
455 * See also: reset_control_release()
456 */
457int reset_control_acquire(struct reset_control *rstc)
458{
459 struct reset_control *rc;
460
461 if (!rstc)
462 return 0;
463
464 if (WARN_ON(IS_ERR(rstc)))
465 return -EINVAL;
466
467 mutex_lock(&reset_list_mutex);
468
469 if (rstc->acquired) {
470 mutex_unlock(&reset_list_mutex);
471 return 0;
472 }
473
474 list_for_each_entry(rc, &rstc->rcdev->reset_control_head, list) {
475 if (rstc != rc && rstc->id == rc->id) {
476 if (rc->acquired) {
477 mutex_unlock(&reset_list_mutex);
478 return -EBUSY;
479 }
480 }
481 }
482
483 rstc->acquired = true;
484
485 mutex_unlock(&reset_list_mutex);
486 return 0;
487}
488EXPORT_SYMBOL_GPL(reset_control_acquire);
489
490/**
491 * reset_control_release() - releases exclusive access to a reset control
492 * @rstc: reset control
493 *
494 * Releases exclusive access right to a reset control previously obtained by a
495 * call to reset_control_acquire(). Until a consumer calls this function, no
496 * other consumers will be granted exclusive access.
497 *
498 * See also: reset_control_acquire()
499 */
500void reset_control_release(struct reset_control *rstc)
501{
502 if (!rstc || WARN_ON(IS_ERR(rstc)))
503 return;
504
505 rstc->acquired = false;
506}
507EXPORT_SYMBOL_GPL(reset_control_release);
508
409static struct reset_control *__reset_control_get_internal( 509static struct reset_control *__reset_control_get_internal(
410 struct reset_controller_dev *rcdev, 510 struct reset_controller_dev *rcdev,
411 unsigned int index, bool shared) 511 unsigned int index, bool shared, bool acquired)
412{ 512{
413 struct reset_control *rstc; 513 struct reset_control *rstc;
414 514
@@ -416,6 +516,14 @@ static struct reset_control *__reset_control_get_internal(
416 516
417 list_for_each_entry(rstc, &rcdev->reset_control_head, list) { 517 list_for_each_entry(rstc, &rcdev->reset_control_head, list) {
418 if (rstc->id == index) { 518 if (rstc->id == index) {
519 /*
520 * Allow creating a secondary exclusive reset_control
521 * that is initially not acquired for an already
522 * controlled reset line.
523 */
524 if (!rstc->shared && !shared && !acquired)
525 break;
526
419 if (WARN_ON(!rstc->shared || !shared)) 527 if (WARN_ON(!rstc->shared || !shared))
420 return ERR_PTR(-EBUSY); 528 return ERR_PTR(-EBUSY);
421 529
@@ -434,6 +542,7 @@ static struct reset_control *__reset_control_get_internal(
434 list_add(&rstc->list, &rcdev->reset_control_head); 542 list_add(&rstc->list, &rcdev->reset_control_head);
435 rstc->id = index; 543 rstc->id = index;
436 kref_init(&rstc->refcnt); 544 kref_init(&rstc->refcnt);
545 rstc->acquired = acquired;
437 rstc->shared = shared; 546 rstc->shared = shared;
438 547
439 return rstc; 548 return rstc;
@@ -461,7 +570,7 @@ static void __reset_control_put_internal(struct reset_control *rstc)
461 570
462struct reset_control *__of_reset_control_get(struct device_node *node, 571struct reset_control *__of_reset_control_get(struct device_node *node,
463 const char *id, int index, bool shared, 572 const char *id, int index, bool shared,
464 bool optional) 573 bool optional, bool acquired)
465{ 574{
466 struct reset_control *rstc; 575 struct reset_control *rstc;
467 struct reset_controller_dev *r, *rcdev; 576 struct reset_controller_dev *r, *rcdev;
@@ -514,7 +623,7 @@ struct reset_control *__of_reset_control_get(struct device_node *node,
514 } 623 }
515 624
516 /* reset_list_mutex also protects the rcdev's reset_control list */ 625 /* reset_list_mutex also protects the rcdev's reset_control list */
517 rstc = __reset_control_get_internal(rcdev, rstc_id, shared); 626 rstc = __reset_control_get_internal(rcdev, rstc_id, shared, acquired);
518 627
519out: 628out:
520 mutex_unlock(&reset_list_mutex); 629 mutex_unlock(&reset_list_mutex);
@@ -544,7 +653,7 @@ __reset_controller_by_name(const char *name)
544 653
545static struct reset_control * 654static struct reset_control *
546__reset_control_get_from_lookup(struct device *dev, const char *con_id, 655__reset_control_get_from_lookup(struct device *dev, const char *con_id,
547 bool shared, bool optional) 656 bool shared, bool optional, bool acquired)
548{ 657{
549 const struct reset_control_lookup *lookup; 658 const struct reset_control_lookup *lookup;
550 struct reset_controller_dev *rcdev; 659 struct reset_controller_dev *rcdev;
@@ -574,7 +683,7 @@ __reset_control_get_from_lookup(struct device *dev, const char *con_id,
574 683
575 rstc = __reset_control_get_internal(rcdev, 684 rstc = __reset_control_get_internal(rcdev,
576 lookup->index, 685 lookup->index,
577 shared); 686 shared, acquired);
578 mutex_unlock(&reset_list_mutex); 687 mutex_unlock(&reset_list_mutex);
579 break; 688 break;
580 } 689 }
@@ -589,13 +698,18 @@ __reset_control_get_from_lookup(struct device *dev, const char *con_id,
589} 698}
590 699
591struct reset_control *__reset_control_get(struct device *dev, const char *id, 700struct reset_control *__reset_control_get(struct device *dev, const char *id,
592 int index, bool shared, bool optional) 701 int index, bool shared, bool optional,
702 bool acquired)
593{ 703{
704 if (WARN_ON(shared && acquired))
705 return ERR_PTR(-EINVAL);
706
594 if (dev->of_node) 707 if (dev->of_node)
595 return __of_reset_control_get(dev->of_node, id, index, shared, 708 return __of_reset_control_get(dev->of_node, id, index, shared,
596 optional); 709 optional, acquired);
597 710
598 return __reset_control_get_from_lookup(dev, id, shared, optional); 711 return __reset_control_get_from_lookup(dev, id, shared, optional,
712 acquired);
599} 713}
600EXPORT_SYMBOL_GPL(__reset_control_get); 714EXPORT_SYMBOL_GPL(__reset_control_get);
601 715
@@ -636,7 +750,7 @@ static void devm_reset_control_release(struct device *dev, void *res)
636 750
637struct reset_control *__devm_reset_control_get(struct device *dev, 751struct reset_control *__devm_reset_control_get(struct device *dev,
638 const char *id, int index, bool shared, 752 const char *id, int index, bool shared,
639 bool optional) 753 bool optional, bool acquired)
640{ 754{
641 struct reset_control **ptr, *rstc; 755 struct reset_control **ptr, *rstc;
642 756
@@ -645,7 +759,7 @@ struct reset_control *__devm_reset_control_get(struct device *dev,
645 if (!ptr) 759 if (!ptr)
646 return ERR_PTR(-ENOMEM); 760 return ERR_PTR(-ENOMEM);
647 761
648 rstc = __reset_control_get(dev, id, index, shared, optional); 762 rstc = __reset_control_get(dev, id, index, shared, optional, acquired);
649 if (!IS_ERR(rstc)) { 763 if (!IS_ERR(rstc)) {
650 *ptr = rstc; 764 *ptr = rstc;
651 devres_add(dev, ptr); 765 devres_add(dev, ptr);
@@ -672,7 +786,7 @@ int __device_reset(struct device *dev, bool optional)
672 struct reset_control *rstc; 786 struct reset_control *rstc;
673 int ret; 787 int ret;
674 788
675 rstc = __reset_control_get(dev, NULL, 0, 0, optional); 789 rstc = __reset_control_get(dev, NULL, 0, 0, optional, true);
676 if (IS_ERR(rstc)) 790 if (IS_ERR(rstc))
677 return PTR_ERR(rstc); 791 return PTR_ERR(rstc);
678 792
@@ -736,7 +850,8 @@ of_reset_control_array_get(struct device_node *np, bool shared, bool optional)
736 return ERR_PTR(-ENOMEM); 850 return ERR_PTR(-ENOMEM);
737 851
738 for (i = 0; i < num; i++) { 852 for (i = 0; i < num; i++) {
739 rstc = __of_reset_control_get(np, NULL, i, shared, optional); 853 rstc = __of_reset_control_get(np, NULL, i, shared, optional,
854 true);
740 if (IS_ERR(rstc)) 855 if (IS_ERR(rstc))
741 goto err_rst; 856 goto err_rst;
742 resets->rstc[i] = rstc; 857 resets->rstc[i] = rstc;