diff options
| -rw-r--r-- | drivers/reset/core.c | 180 | ||||
| -rw-r--r-- | drivers/usb/dwc3/dwc3-of-simple.c | 3 | ||||
| -rw-r--r-- | include/linux/reset.h | 113 |
3 files changed, 255 insertions, 41 deletions
diff --git a/drivers/reset/core.c b/drivers/reset/core.c index 9582efb70025..81ea77cba123 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 | ||
| 68 | static 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 |
| @@ -232,6 +245,34 @@ err: | |||
| 232 | return ret; | 245 | return ret; |
| 233 | } | 246 | } |
| 234 | 247 | ||
| 248 | static int reset_control_array_acquire(struct reset_control_array *resets) | ||
| 249 | { | ||
| 250 | unsigned int i; | ||
| 251 | int err; | ||
| 252 | |||
| 253 | for (i = 0; i < resets->num_rstcs; i++) { | ||
| 254 | err = reset_control_acquire(resets->rstc[i]); | ||
| 255 | if (err < 0) | ||
| 256 | goto release; | ||
| 257 | } | ||
| 258 | |||
| 259 | return 0; | ||
| 260 | |||
| 261 | release: | ||
| 262 | while (i--) | ||
| 263 | reset_control_release(resets->rstc[i]); | ||
| 264 | |||
| 265 | return err; | ||
| 266 | } | ||
| 267 | |||
| 268 | static void reset_control_array_release(struct reset_control_array *resets) | ||
| 269 | { | ||
| 270 | unsigned int i; | ||
| 271 | |||
| 272 | for (i = 0; i < resets->num_rstcs; i++) | ||
| 273 | reset_control_release(resets->rstc[i]); | ||
| 274 | } | ||
| 275 | |||
| 235 | static inline bool reset_control_is_array(struct reset_control *rstc) | 276 | static inline bool reset_control_is_array(struct reset_control *rstc) |
| 236 | { | 277 | { |
| 237 | return rstc->array; | 278 | return rstc->array; |
| @@ -272,6 +313,9 @@ int reset_control_reset(struct reset_control *rstc) | |||
| 272 | 313 | ||
| 273 | if (atomic_inc_return(&rstc->triggered_count) != 1) | 314 | if (atomic_inc_return(&rstc->triggered_count) != 1) |
| 274 | return 0; | 315 | return 0; |
| 316 | } else { | ||
| 317 | if (!rstc->acquired) | ||
| 318 | return -EPERM; | ||
| 275 | } | 319 | } |
| 276 | 320 | ||
| 277 | ret = rstc->rcdev->ops->reset(rstc->rcdev, rstc->id); | 321 | ret = rstc->rcdev->ops->reset(rstc->rcdev, rstc->id); |
| @@ -334,6 +378,12 @@ int reset_control_assert(struct reset_control *rstc) | |||
| 334 | */ | 378 | */ |
| 335 | if (!rstc->rcdev->ops->assert) | 379 | if (!rstc->rcdev->ops->assert) |
| 336 | return -ENOTSUPP; | 380 | return -ENOTSUPP; |
| 381 | |||
| 382 | if (!rstc->acquired) { | ||
| 383 | WARN(1, "reset %s (ID: %u) is not acquired\n", | ||
| 384 | rcdev_name(rstc->rcdev), rstc->id); | ||
| 385 | return -EPERM; | ||
| 386 | } | ||
| 337 | } | 387 | } |
| 338 | 388 | ||
| 339 | return rstc->rcdev->ops->assert(rstc->rcdev, rstc->id); | 389 | return rstc->rcdev->ops->assert(rstc->rcdev, rstc->id); |
| @@ -369,6 +419,12 @@ int reset_control_deassert(struct reset_control *rstc) | |||
| 369 | 419 | ||
| 370 | if (atomic_inc_return(&rstc->deassert_count) != 1) | 420 | if (atomic_inc_return(&rstc->deassert_count) != 1) |
| 371 | return 0; | 421 | return 0; |
| 422 | } else { | ||
| 423 | if (!rstc->acquired) { | ||
| 424 | WARN(1, "reset %s (ID: %u) is not acquired\n", | ||
| 425 | rcdev_name(rstc->rcdev), rstc->id); | ||
| 426 | return -EPERM; | ||
| 427 | } | ||
| 372 | } | 428 | } |
| 373 | 429 | ||
| 374 | /* | 430 | /* |
| @@ -406,9 +462,87 @@ int reset_control_status(struct reset_control *rstc) | |||
| 406 | } | 462 | } |
| 407 | EXPORT_SYMBOL_GPL(reset_control_status); | 463 | EXPORT_SYMBOL_GPL(reset_control_status); |
| 408 | 464 | ||
| 465 | /** | ||
| 466 | * reset_control_acquire() - acquires a reset control for exclusive use | ||
| 467 | * @rstc: reset control | ||
| 468 | * | ||
| 469 | * This is used to explicitly acquire a reset control for exclusive use. Note | ||
| 470 | * that exclusive resets are requested as acquired by default. In order for a | ||
| 471 | * second consumer to be able to control the reset, the first consumer has to | ||
| 472 | * release it first. Typically the easiest way to achieve this is to call the | ||
| 473 | * reset_control_get_exclusive_released() to obtain an instance of the reset | ||
| 474 | * control. Such reset controls are not acquired by default. | ||
| 475 | * | ||
| 476 | * Consumers implementing shared access to an exclusive reset need to follow | ||
| 477 | * a specific protocol in order to work together. Before consumers can change | ||
| 478 | * a reset they must acquire exclusive access using reset_control_acquire(). | ||
| 479 | * After they are done operating the reset, they must release exclusive access | ||
| 480 | * with a call to reset_control_release(). Consumers are not granted exclusive | ||
| 481 | * access to the reset as long as another consumer hasn't released a reset. | ||
| 482 | * | ||
| 483 | * See also: reset_control_release() | ||
| 484 | */ | ||
| 485 | int reset_control_acquire(struct reset_control *rstc) | ||
| 486 | { | ||
| 487 | struct reset_control *rc; | ||
| 488 | |||
| 489 | if (!rstc) | ||
| 490 | return 0; | ||
| 491 | |||
| 492 | if (WARN_ON(IS_ERR(rstc))) | ||
| 493 | return -EINVAL; | ||
| 494 | |||
| 495 | if (reset_control_is_array(rstc)) | ||
| 496 | return reset_control_array_acquire(rstc_to_array(rstc)); | ||
| 497 | |||
| 498 | mutex_lock(&reset_list_mutex); | ||
| 499 | |||
| 500 | if (rstc->acquired) { | ||
| 501 | mutex_unlock(&reset_list_mutex); | ||
| 502 | return 0; | ||
| 503 | } | ||
| 504 | |||
| 505 | list_for_each_entry(rc, &rstc->rcdev->reset_control_head, list) { | ||
| 506 | if (rstc != rc && rstc->id == rc->id) { | ||
| 507 | if (rc->acquired) { | ||
| 508 | mutex_unlock(&reset_list_mutex); | ||
| 509 | return -EBUSY; | ||
| 510 | } | ||
| 511 | } | ||
| 512 | } | ||
| 513 | |||
| 514 | rstc->acquired = true; | ||
| 515 | |||
| 516 | mutex_unlock(&reset_list_mutex); | ||
| 517 | return 0; | ||
| 518 | } | ||
| 519 | EXPORT_SYMBOL_GPL(reset_control_acquire); | ||
| 520 | |||
| 521 | /** | ||
| 522 | * reset_control_release() - releases exclusive access to a reset control | ||
| 523 | * @rstc: reset control | ||
| 524 | * | ||
| 525 | * Releases exclusive access right to a reset control previously obtained by a | ||
| 526 | * call to reset_control_acquire(). Until a consumer calls this function, no | ||
| 527 | * other consumers will be granted exclusive access. | ||
| 528 | * | ||
| 529 | * See also: reset_control_acquire() | ||
| 530 | */ | ||
| 531 | void reset_control_release(struct reset_control *rstc) | ||
| 532 | { | ||
| 533 | if (!rstc || WARN_ON(IS_ERR(rstc))) | ||
| 534 | return; | ||
| 535 | |||
| 536 | if (reset_control_is_array(rstc)) | ||
| 537 | reset_control_array_release(rstc_to_array(rstc)); | ||
| 538 | else | ||
| 539 | rstc->acquired = false; | ||
| 540 | } | ||
| 541 | EXPORT_SYMBOL_GPL(reset_control_release); | ||
| 542 | |||
| 409 | static struct reset_control *__reset_control_get_internal( | 543 | static struct reset_control *__reset_control_get_internal( |
| 410 | struct reset_controller_dev *rcdev, | 544 | struct reset_controller_dev *rcdev, |
| 411 | unsigned int index, bool shared) | 545 | unsigned int index, bool shared, bool acquired) |
| 412 | { | 546 | { |
| 413 | struct reset_control *rstc; | 547 | struct reset_control *rstc; |
| 414 | 548 | ||
| @@ -416,6 +550,14 @@ static struct reset_control *__reset_control_get_internal( | |||
| 416 | 550 | ||
| 417 | list_for_each_entry(rstc, &rcdev->reset_control_head, list) { | 551 | list_for_each_entry(rstc, &rcdev->reset_control_head, list) { |
| 418 | if (rstc->id == index) { | 552 | if (rstc->id == index) { |
| 553 | /* | ||
| 554 | * Allow creating a secondary exclusive reset_control | ||
| 555 | * that is initially not acquired for an already | ||
| 556 | * controlled reset line. | ||
| 557 | */ | ||
| 558 | if (!rstc->shared && !shared && !acquired) | ||
| 559 | break; | ||
| 560 | |||
| 419 | if (WARN_ON(!rstc->shared || !shared)) | 561 | if (WARN_ON(!rstc->shared || !shared)) |
| 420 | return ERR_PTR(-EBUSY); | 562 | return ERR_PTR(-EBUSY); |
| 421 | 563 | ||
| @@ -434,6 +576,7 @@ static struct reset_control *__reset_control_get_internal( | |||
| 434 | list_add(&rstc->list, &rcdev->reset_control_head); | 576 | list_add(&rstc->list, &rcdev->reset_control_head); |
| 435 | rstc->id = index; | 577 | rstc->id = index; |
| 436 | kref_init(&rstc->refcnt); | 578 | kref_init(&rstc->refcnt); |
| 579 | rstc->acquired = acquired; | ||
| 437 | rstc->shared = shared; | 580 | rstc->shared = shared; |
| 438 | 581 | ||
| 439 | return rstc; | 582 | return rstc; |
| @@ -461,7 +604,7 @@ static void __reset_control_put_internal(struct reset_control *rstc) | |||
| 461 | 604 | ||
| 462 | struct reset_control *__of_reset_control_get(struct device_node *node, | 605 | struct reset_control *__of_reset_control_get(struct device_node *node, |
| 463 | const char *id, int index, bool shared, | 606 | const char *id, int index, bool shared, |
| 464 | bool optional) | 607 | bool optional, bool acquired) |
| 465 | { | 608 | { |
| 466 | struct reset_control *rstc; | 609 | struct reset_control *rstc; |
| 467 | struct reset_controller_dev *r, *rcdev; | 610 | struct reset_controller_dev *r, *rcdev; |
| @@ -514,7 +657,7 @@ struct reset_control *__of_reset_control_get(struct device_node *node, | |||
| 514 | } | 657 | } |
| 515 | 658 | ||
| 516 | /* reset_list_mutex also protects the rcdev's reset_control list */ | 659 | /* reset_list_mutex also protects the rcdev's reset_control list */ |
| 517 | rstc = __reset_control_get_internal(rcdev, rstc_id, shared); | 660 | rstc = __reset_control_get_internal(rcdev, rstc_id, shared, acquired); |
| 518 | 661 | ||
| 519 | out: | 662 | out: |
| 520 | mutex_unlock(&reset_list_mutex); | 663 | mutex_unlock(&reset_list_mutex); |
| @@ -544,7 +687,7 @@ __reset_controller_by_name(const char *name) | |||
| 544 | 687 | ||
| 545 | static struct reset_control * | 688 | static struct reset_control * |
| 546 | __reset_control_get_from_lookup(struct device *dev, const char *con_id, | 689 | __reset_control_get_from_lookup(struct device *dev, const char *con_id, |
| 547 | bool shared, bool optional) | 690 | bool shared, bool optional, bool acquired) |
| 548 | { | 691 | { |
| 549 | const struct reset_control_lookup *lookup; | 692 | const struct reset_control_lookup *lookup; |
| 550 | struct reset_controller_dev *rcdev; | 693 | struct reset_controller_dev *rcdev; |
| @@ -574,7 +717,7 @@ __reset_control_get_from_lookup(struct device *dev, const char *con_id, | |||
| 574 | 717 | ||
| 575 | rstc = __reset_control_get_internal(rcdev, | 718 | rstc = __reset_control_get_internal(rcdev, |
| 576 | lookup->index, | 719 | lookup->index, |
| 577 | shared); | 720 | shared, acquired); |
| 578 | mutex_unlock(&reset_list_mutex); | 721 | mutex_unlock(&reset_list_mutex); |
| 579 | break; | 722 | break; |
| 580 | } | 723 | } |
| @@ -589,13 +732,18 @@ __reset_control_get_from_lookup(struct device *dev, const char *con_id, | |||
| 589 | } | 732 | } |
| 590 | 733 | ||
| 591 | struct reset_control *__reset_control_get(struct device *dev, const char *id, | 734 | struct reset_control *__reset_control_get(struct device *dev, const char *id, |
| 592 | int index, bool shared, bool optional) | 735 | int index, bool shared, bool optional, |
| 736 | bool acquired) | ||
| 593 | { | 737 | { |
| 738 | if (WARN_ON(shared && acquired)) | ||
| 739 | return ERR_PTR(-EINVAL); | ||
| 740 | |||
| 594 | if (dev->of_node) | 741 | if (dev->of_node) |
| 595 | return __of_reset_control_get(dev->of_node, id, index, shared, | 742 | return __of_reset_control_get(dev->of_node, id, index, shared, |
| 596 | optional); | 743 | optional, acquired); |
| 597 | 744 | ||
| 598 | return __reset_control_get_from_lookup(dev, id, shared, optional); | 745 | return __reset_control_get_from_lookup(dev, id, shared, optional, |
| 746 | acquired); | ||
| 599 | } | 747 | } |
| 600 | EXPORT_SYMBOL_GPL(__reset_control_get); | 748 | EXPORT_SYMBOL_GPL(__reset_control_get); |
| 601 | 749 | ||
| @@ -636,7 +784,7 @@ static void devm_reset_control_release(struct device *dev, void *res) | |||
| 636 | 784 | ||
| 637 | struct reset_control *__devm_reset_control_get(struct device *dev, | 785 | struct reset_control *__devm_reset_control_get(struct device *dev, |
| 638 | const char *id, int index, bool shared, | 786 | const char *id, int index, bool shared, |
| 639 | bool optional) | 787 | bool optional, bool acquired) |
| 640 | { | 788 | { |
| 641 | struct reset_control **ptr, *rstc; | 789 | struct reset_control **ptr, *rstc; |
| 642 | 790 | ||
| @@ -645,7 +793,7 @@ struct reset_control *__devm_reset_control_get(struct device *dev, | |||
| 645 | if (!ptr) | 793 | if (!ptr) |
| 646 | return ERR_PTR(-ENOMEM); | 794 | return ERR_PTR(-ENOMEM); |
| 647 | 795 | ||
| 648 | rstc = __reset_control_get(dev, id, index, shared, optional); | 796 | rstc = __reset_control_get(dev, id, index, shared, optional, acquired); |
| 649 | if (!IS_ERR(rstc)) { | 797 | if (!IS_ERR(rstc)) { |
| 650 | *ptr = rstc; | 798 | *ptr = rstc; |
| 651 | devres_add(dev, ptr); | 799 | devres_add(dev, ptr); |
| @@ -672,7 +820,7 @@ int __device_reset(struct device *dev, bool optional) | |||
| 672 | struct reset_control *rstc; | 820 | struct reset_control *rstc; |
| 673 | int ret; | 821 | int ret; |
| 674 | 822 | ||
| 675 | rstc = __reset_control_get(dev, NULL, 0, 0, optional); | 823 | rstc = __reset_control_get(dev, NULL, 0, 0, optional, true); |
| 676 | if (IS_ERR(rstc)) | 824 | if (IS_ERR(rstc)) |
| 677 | return PTR_ERR(rstc); | 825 | return PTR_ERR(rstc); |
| 678 | 826 | ||
| @@ -716,12 +864,15 @@ static int of_reset_control_get_count(struct device_node *node) | |||
| 716 | * @np: device node for the device that requests the reset controls array | 864 | * @np: device node for the device that requests the reset controls array |
| 717 | * @shared: whether reset controls are shared or not | 865 | * @shared: whether reset controls are shared or not |
| 718 | * @optional: whether it is optional to get the reset controls | 866 | * @optional: whether it is optional to get the reset controls |
| 867 | * @acquired: only one reset control may be acquired for a given controller | ||
| 868 | * and ID | ||
| 719 | * | 869 | * |
| 720 | * Returns pointer to allocated reset_control_array on success or | 870 | * Returns pointer to allocated reset_control_array on success or |
| 721 | * error on failure | 871 | * error on failure |
| 722 | */ | 872 | */ |
| 723 | struct reset_control * | 873 | struct reset_control * |
| 724 | of_reset_control_array_get(struct device_node *np, bool shared, bool optional) | 874 | of_reset_control_array_get(struct device_node *np, bool shared, bool optional, |
| 875 | bool acquired) | ||
| 725 | { | 876 | { |
| 726 | struct reset_control_array *resets; | 877 | struct reset_control_array *resets; |
| 727 | struct reset_control *rstc; | 878 | struct reset_control *rstc; |
| @@ -736,7 +887,8 @@ of_reset_control_array_get(struct device_node *np, bool shared, bool optional) | |||
| 736 | return ERR_PTR(-ENOMEM); | 887 | return ERR_PTR(-ENOMEM); |
| 737 | 888 | ||
| 738 | for (i = 0; i < num; i++) { | 889 | for (i = 0; i < num; i++) { |
| 739 | rstc = __of_reset_control_get(np, NULL, i, shared, optional); | 890 | rstc = __of_reset_control_get(np, NULL, i, shared, optional, |
| 891 | acquired); | ||
| 740 | if (IS_ERR(rstc)) | 892 | if (IS_ERR(rstc)) |
| 741 | goto err_rst; | 893 | goto err_rst; |
| 742 | resets->rstc[i] = rstc; | 894 | resets->rstc[i] = rstc; |
| @@ -783,7 +935,7 @@ devm_reset_control_array_get(struct device *dev, bool shared, bool optional) | |||
| 783 | if (!devres) | 935 | if (!devres) |
| 784 | return ERR_PTR(-ENOMEM); | 936 | return ERR_PTR(-ENOMEM); |
| 785 | 937 | ||
| 786 | rstc = of_reset_control_array_get(dev->of_node, shared, optional); | 938 | rstc = of_reset_control_array_get(dev->of_node, shared, optional, true); |
| 787 | if (IS_ERR(rstc)) { | 939 | if (IS_ERR(rstc)) { |
| 788 | devres_free(devres); | 940 | devres_free(devres); |
| 789 | return rstc; | 941 | return rstc; |
diff --git a/drivers/usb/dwc3/dwc3-of-simple.c b/drivers/usb/dwc3/dwc3-of-simple.c index 4c2771c5e727..67ce2037472d 100644 --- a/drivers/usb/dwc3/dwc3-of-simple.c +++ b/drivers/usb/dwc3/dwc3-of-simple.c | |||
| @@ -107,7 +107,8 @@ static int dwc3_of_simple_probe(struct platform_device *pdev) | |||
| 107 | simple->pulse_resets = true; | 107 | simple->pulse_resets = true; |
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | simple->resets = of_reset_control_array_get(np, shared_resets, true); | 110 | simple->resets = of_reset_control_array_get(np, shared_resets, true, |
| 111 | true); | ||
| 111 | if (IS_ERR(simple->resets)) { | 112 | if (IS_ERR(simple->resets)) { |
| 112 | ret = PTR_ERR(simple->resets); | 113 | ret = PTR_ERR(simple->resets); |
| 113 | dev_err(dev, "failed to get device resets, err=%d\n", ret); | 114 | dev_err(dev, "failed to get device resets, err=%d\n", ret); |
diff --git a/include/linux/reset.h b/include/linux/reset.h index c1901b61ca30..95d555c2130a 100644 --- a/include/linux/reset.h +++ b/include/linux/reset.h | |||
| @@ -14,23 +14,26 @@ int reset_control_reset(struct reset_control *rstc); | |||
| 14 | int reset_control_assert(struct reset_control *rstc); | 14 | int reset_control_assert(struct reset_control *rstc); |
| 15 | int reset_control_deassert(struct reset_control *rstc); | 15 | int reset_control_deassert(struct reset_control *rstc); |
| 16 | int reset_control_status(struct reset_control *rstc); | 16 | int reset_control_status(struct reset_control *rstc); |
| 17 | int reset_control_acquire(struct reset_control *rstc); | ||
| 18 | void reset_control_release(struct reset_control *rstc); | ||
| 17 | 19 | ||
| 18 | struct reset_control *__of_reset_control_get(struct device_node *node, | 20 | struct reset_control *__of_reset_control_get(struct device_node *node, |
| 19 | const char *id, int index, bool shared, | 21 | const char *id, int index, bool shared, |
| 20 | bool optional); | 22 | bool optional, bool acquired); |
| 21 | struct reset_control *__reset_control_get(struct device *dev, const char *id, | 23 | struct reset_control *__reset_control_get(struct device *dev, const char *id, |
| 22 | int index, bool shared, | 24 | int index, bool shared, |
| 23 | bool optional); | 25 | bool optional, bool acquired); |
| 24 | void reset_control_put(struct reset_control *rstc); | 26 | void reset_control_put(struct reset_control *rstc); |
| 25 | int __device_reset(struct device *dev, bool optional); | 27 | int __device_reset(struct device *dev, bool optional); |
| 26 | struct reset_control *__devm_reset_control_get(struct device *dev, | 28 | struct reset_control *__devm_reset_control_get(struct device *dev, |
| 27 | const char *id, int index, bool shared, | 29 | const char *id, int index, bool shared, |
| 28 | bool optional); | 30 | bool optional, bool acquired); |
| 29 | 31 | ||
| 30 | struct reset_control *devm_reset_control_array_get(struct device *dev, | 32 | struct reset_control *devm_reset_control_array_get(struct device *dev, |
| 31 | bool shared, bool optional); | 33 | bool shared, bool optional); |
| 32 | struct reset_control *of_reset_control_array_get(struct device_node *np, | 34 | struct reset_control *of_reset_control_array_get(struct device_node *np, |
| 33 | bool shared, bool optional); | 35 | bool shared, bool optional, |
| 36 | bool acquired); | ||
| 34 | 37 | ||
| 35 | int reset_control_get_count(struct device *dev); | 38 | int reset_control_get_count(struct device *dev); |
| 36 | 39 | ||
| @@ -56,6 +59,15 @@ static inline int reset_control_status(struct reset_control *rstc) | |||
| 56 | return 0; | 59 | return 0; |
| 57 | } | 60 | } |
| 58 | 61 | ||
| 62 | static inline int reset_control_acquire(struct reset_control *rstc) | ||
| 63 | { | ||
| 64 | return 0; | ||
| 65 | } | ||
| 66 | |||
| 67 | static inline void reset_control_release(struct reset_control *rstc) | ||
| 68 | { | ||
| 69 | } | ||
| 70 | |||
| 59 | static inline void reset_control_put(struct reset_control *rstc) | 71 | static inline void reset_control_put(struct reset_control *rstc) |
| 60 | { | 72 | { |
| 61 | } | 73 | } |
| @@ -68,21 +80,23 @@ static inline int __device_reset(struct device *dev, bool optional) | |||
| 68 | static inline struct reset_control *__of_reset_control_get( | 80 | static inline struct reset_control *__of_reset_control_get( |
| 69 | struct device_node *node, | 81 | struct device_node *node, |
| 70 | const char *id, int index, bool shared, | 82 | const char *id, int index, bool shared, |
| 71 | bool optional) | 83 | bool optional, bool acquired) |
| 72 | { | 84 | { |
| 73 | return optional ? NULL : ERR_PTR(-ENOTSUPP); | 85 | return optional ? NULL : ERR_PTR(-ENOTSUPP); |
| 74 | } | 86 | } |
| 75 | 87 | ||
| 76 | static inline struct reset_control *__reset_control_get( | 88 | static inline struct reset_control *__reset_control_get( |
| 77 | struct device *dev, const char *id, | 89 | struct device *dev, const char *id, |
| 78 | int index, bool shared, bool optional) | 90 | int index, bool shared, bool optional, |
| 91 | bool acquired) | ||
| 79 | { | 92 | { |
| 80 | return optional ? NULL : ERR_PTR(-ENOTSUPP); | 93 | return optional ? NULL : ERR_PTR(-ENOTSUPP); |
| 81 | } | 94 | } |
| 82 | 95 | ||
| 83 | static inline struct reset_control *__devm_reset_control_get( | 96 | static inline struct reset_control *__devm_reset_control_get( |
| 84 | struct device *dev, const char *id, | 97 | struct device *dev, const char *id, |
| 85 | int index, bool shared, bool optional) | 98 | int index, bool shared, bool optional, |
| 99 | bool acquired) | ||
| 86 | { | 100 | { |
| 87 | return optional ? NULL : ERR_PTR(-ENOTSUPP); | 101 | return optional ? NULL : ERR_PTR(-ENOTSUPP); |
| 88 | } | 102 | } |
| @@ -94,7 +108,8 @@ devm_reset_control_array_get(struct device *dev, bool shared, bool optional) | |||
| 94 | } | 108 | } |
| 95 | 109 | ||
| 96 | static inline struct reset_control * | 110 | static inline struct reset_control * |
| 97 | of_reset_control_array_get(struct device_node *np, bool shared, bool optional) | 111 | of_reset_control_array_get(struct device_node *np, bool shared, bool optional, |
| 112 | bool acquired) | ||
| 98 | { | 113 | { |
| 99 | return optional ? NULL : ERR_PTR(-ENOTSUPP); | 114 | return optional ? NULL : ERR_PTR(-ENOTSUPP); |
| 100 | } | 115 | } |
| @@ -134,7 +149,28 @@ static inline int device_reset_optional(struct device *dev) | |||
| 134 | static inline struct reset_control * | 149 | static inline struct reset_control * |
| 135 | __must_check reset_control_get_exclusive(struct device *dev, const char *id) | 150 | __must_check reset_control_get_exclusive(struct device *dev, const char *id) |
| 136 | { | 151 | { |
| 137 | return __reset_control_get(dev, id, 0, false, false); | 152 | return __reset_control_get(dev, id, 0, false, false, true); |
| 153 | } | ||
| 154 | |||
| 155 | /** | ||
| 156 | * reset_control_get_exclusive_released - Lookup and obtain a temoprarily | ||
| 157 | * exclusive reference to a reset | ||
| 158 | * controller. | ||
| 159 | * @dev: device to be reset by the controller | ||
| 160 | * @id: reset line name | ||
| 161 | * | ||
| 162 | * Returns a struct reset_control or IS_ERR() condition containing errno. | ||
| 163 | * reset-controls returned by this function must be acquired via | ||
| 164 | * reset_control_acquire() before they can be used and should be released | ||
| 165 | * via reset_control_release() afterwards. | ||
| 166 | * | ||
| 167 | * Use of id names is optional. | ||
| 168 | */ | ||
| 169 | static inline struct reset_control * | ||
| 170 | __must_check reset_control_get_exclusive_released(struct device *dev, | ||
| 171 | const char *id) | ||
| 172 | { | ||
| 173 | return __reset_control_get(dev, id, 0, false, false, false); | ||
| 138 | } | 174 | } |
| 139 | 175 | ||
| 140 | /** | 176 | /** |
| @@ -162,19 +198,19 @@ __must_check reset_control_get_exclusive(struct device *dev, const char *id) | |||
| 162 | static inline struct reset_control *reset_control_get_shared( | 198 | static inline struct reset_control *reset_control_get_shared( |
| 163 | struct device *dev, const char *id) | 199 | struct device *dev, const char *id) |
| 164 | { | 200 | { |
| 165 | return __reset_control_get(dev, id, 0, true, false); | 201 | return __reset_control_get(dev, id, 0, true, false, false); |
| 166 | } | 202 | } |
| 167 | 203 | ||
| 168 | static inline struct reset_control *reset_control_get_optional_exclusive( | 204 | static inline struct reset_control *reset_control_get_optional_exclusive( |
| 169 | struct device *dev, const char *id) | 205 | struct device *dev, const char *id) |
| 170 | { | 206 | { |
| 171 | return __reset_control_get(dev, id, 0, false, true); | 207 | return __reset_control_get(dev, id, 0, false, true, true); |
| 172 | } | 208 | } |
| 173 | 209 | ||
| 174 | static inline struct reset_control *reset_control_get_optional_shared( | 210 | static inline struct reset_control *reset_control_get_optional_shared( |
| 175 | struct device *dev, const char *id) | 211 | struct device *dev, const char *id) |
| 176 | { | 212 | { |
| 177 | return __reset_control_get(dev, id, 0, true, true); | 213 | return __reset_control_get(dev, id, 0, true, true, false); |
| 178 | } | 214 | } |
| 179 | 215 | ||
| 180 | /** | 216 | /** |
| @@ -190,7 +226,7 @@ static inline struct reset_control *reset_control_get_optional_shared( | |||
| 190 | static inline struct reset_control *of_reset_control_get_exclusive( | 226 | static inline struct reset_control *of_reset_control_get_exclusive( |
| 191 | struct device_node *node, const char *id) | 227 | struct device_node *node, const char *id) |
| 192 | { | 228 | { |
| 193 | return __of_reset_control_get(node, id, 0, false, false); | 229 | return __of_reset_control_get(node, id, 0, false, false, true); |
| 194 | } | 230 | } |
| 195 | 231 | ||
| 196 | /** | 232 | /** |
| @@ -215,7 +251,7 @@ static inline struct reset_control *of_reset_control_get_exclusive( | |||
| 215 | static inline struct reset_control *of_reset_control_get_shared( | 251 | static inline struct reset_control *of_reset_control_get_shared( |
| 216 | struct device_node *node, const char *id) | 252 | struct device_node *node, const char *id) |
| 217 | { | 253 | { |
| 218 | return __of_reset_control_get(node, id, 0, true, false); | 254 | return __of_reset_control_get(node, id, 0, true, false, false); |
| 219 | } | 255 | } |
| 220 | 256 | ||
| 221 | /** | 257 | /** |
| @@ -232,7 +268,7 @@ static inline struct reset_control *of_reset_control_get_shared( | |||
| 232 | static inline struct reset_control *of_reset_control_get_exclusive_by_index( | 268 | static inline struct reset_control *of_reset_control_get_exclusive_by_index( |
| 233 | struct device_node *node, int index) | 269 | struct device_node *node, int index) |
| 234 | { | 270 | { |
| 235 | return __of_reset_control_get(node, NULL, index, false, false); | 271 | return __of_reset_control_get(node, NULL, index, false, false, true); |
| 236 | } | 272 | } |
| 237 | 273 | ||
| 238 | /** | 274 | /** |
| @@ -260,7 +296,7 @@ static inline struct reset_control *of_reset_control_get_exclusive_by_index( | |||
| 260 | static inline struct reset_control *of_reset_control_get_shared_by_index( | 296 | static inline struct reset_control *of_reset_control_get_shared_by_index( |
| 261 | struct device_node *node, int index) | 297 | struct device_node *node, int index) |
| 262 | { | 298 | { |
| 263 | return __of_reset_control_get(node, NULL, index, true, false); | 299 | return __of_reset_control_get(node, NULL, index, true, false, false); |
| 264 | } | 300 | } |
| 265 | 301 | ||
| 266 | /** | 302 | /** |
| @@ -279,7 +315,26 @@ static inline struct reset_control * | |||
| 279 | __must_check devm_reset_control_get_exclusive(struct device *dev, | 315 | __must_check devm_reset_control_get_exclusive(struct device *dev, |
| 280 | const char *id) | 316 | const char *id) |
| 281 | { | 317 | { |
| 282 | return __devm_reset_control_get(dev, id, 0, false, false); | 318 | return __devm_reset_control_get(dev, id, 0, false, false, true); |
| 319 | } | ||
| 320 | |||
| 321 | /** | ||
| 322 | * devm_reset_control_get_exclusive_released - resource managed | ||
| 323 | * reset_control_get_exclusive_released() | ||
| 324 | * @dev: device to be reset by the controller | ||
| 325 | * @id: reset line name | ||
| 326 | * | ||
| 327 | * Managed reset_control_get_exclusive_released(). For reset controllers | ||
| 328 | * returned from this function, reset_control_put() is called automatically on | ||
| 329 | * driver detach. | ||
| 330 | * | ||
| 331 | * See reset_control_get_exclusive_released() for more information. | ||
| 332 | */ | ||
| 333 | static inline struct reset_control * | ||
| 334 | __must_check devm_reset_control_get_exclusive_released(struct device *dev, | ||
| 335 | const char *id) | ||
| 336 | { | ||
| 337 | return __devm_reset_control_get(dev, id, 0, false, false, false); | ||
| 283 | } | 338 | } |
| 284 | 339 | ||
| 285 | /** | 340 | /** |
| @@ -294,19 +349,19 @@ __must_check devm_reset_control_get_exclusive(struct device *dev, | |||
| 294 | static inline struct reset_control *devm_reset_control_get_shared( | 349 | static inline struct reset_control *devm_reset_control_get_shared( |
| 295 | struct device *dev, const char *id) | 350 | struct device *dev, const char *id) |
| 296 | { | 351 | { |
| 297 | return __devm_reset_control_get(dev, id, 0, true, false); | 352 | return __devm_reset_control_get(dev, id, 0, true, false, false); |
| 298 | } | 353 | } |
| 299 | 354 | ||
| 300 | static inline struct reset_control *devm_reset_control_get_optional_exclusive( | 355 | static inline struct reset_control *devm_reset_control_get_optional_exclusive( |
| 301 | struct device *dev, const char *id) | 356 | struct device *dev, const char *id) |
| 302 | { | 357 | { |
| 303 | return __devm_reset_control_get(dev, id, 0, false, true); | 358 | return __devm_reset_control_get(dev, id, 0, false, true, true); |
| 304 | } | 359 | } |
| 305 | 360 | ||
| 306 | static inline struct reset_control *devm_reset_control_get_optional_shared( | 361 | static inline struct reset_control *devm_reset_control_get_optional_shared( |
| 307 | struct device *dev, const char *id) | 362 | struct device *dev, const char *id) |
| 308 | { | 363 | { |
| 309 | return __devm_reset_control_get(dev, id, 0, true, true); | 364 | return __devm_reset_control_get(dev, id, 0, true, true, false); |
| 310 | } | 365 | } |
| 311 | 366 | ||
| 312 | /** | 367 | /** |
| @@ -324,7 +379,7 @@ static inline struct reset_control *devm_reset_control_get_optional_shared( | |||
| 324 | static inline struct reset_control * | 379 | static inline struct reset_control * |
| 325 | devm_reset_control_get_exclusive_by_index(struct device *dev, int index) | 380 | devm_reset_control_get_exclusive_by_index(struct device *dev, int index) |
| 326 | { | 381 | { |
| 327 | return __devm_reset_control_get(dev, NULL, index, false, false); | 382 | return __devm_reset_control_get(dev, NULL, index, false, false, true); |
| 328 | } | 383 | } |
| 329 | 384 | ||
| 330 | /** | 385 | /** |
| @@ -340,7 +395,7 @@ devm_reset_control_get_exclusive_by_index(struct device *dev, int index) | |||
| 340 | static inline struct reset_control * | 395 | static inline struct reset_control * |
| 341 | devm_reset_control_get_shared_by_index(struct device *dev, int index) | 396 | devm_reset_control_get_shared_by_index(struct device *dev, int index) |
| 342 | { | 397 | { |
| 343 | return __devm_reset_control_get(dev, NULL, index, true, false); | 398 | return __devm_reset_control_get(dev, NULL, index, true, false, false); |
| 344 | } | 399 | } |
| 345 | 400 | ||
| 346 | /* | 401 | /* |
| @@ -412,24 +467,30 @@ devm_reset_control_array_get_optional_shared(struct device *dev) | |||
| 412 | static inline struct reset_control * | 467 | static inline struct reset_control * |
| 413 | of_reset_control_array_get_exclusive(struct device_node *node) | 468 | of_reset_control_array_get_exclusive(struct device_node *node) |
| 414 | { | 469 | { |
| 415 | return of_reset_control_array_get(node, false, false); | 470 | return of_reset_control_array_get(node, false, false, true); |
| 471 | } | ||
| 472 | |||
| 473 | static inline struct reset_control * | ||
| 474 | of_reset_control_array_get_exclusive_released(struct device_node *node) | ||
| 475 | { | ||
| 476 | return of_reset_control_array_get(node, false, false, false); | ||
| 416 | } | 477 | } |
| 417 | 478 | ||
| 418 | static inline struct reset_control * | 479 | static inline struct reset_control * |
| 419 | of_reset_control_array_get_shared(struct device_node *node) | 480 | of_reset_control_array_get_shared(struct device_node *node) |
| 420 | { | 481 | { |
| 421 | return of_reset_control_array_get(node, true, false); | 482 | return of_reset_control_array_get(node, true, false, true); |
| 422 | } | 483 | } |
| 423 | 484 | ||
| 424 | static inline struct reset_control * | 485 | static inline struct reset_control * |
| 425 | of_reset_control_array_get_optional_exclusive(struct device_node *node) | 486 | of_reset_control_array_get_optional_exclusive(struct device_node *node) |
| 426 | { | 487 | { |
| 427 | return of_reset_control_array_get(node, false, true); | 488 | return of_reset_control_array_get(node, false, true, true); |
| 428 | } | 489 | } |
| 429 | 490 | ||
| 430 | static inline struct reset_control * | 491 | static inline struct reset_control * |
| 431 | of_reset_control_array_get_optional_shared(struct device_node *node) | 492 | of_reset_control_array_get_optional_shared(struct device_node *node) |
| 432 | { | 493 | { |
| 433 | return of_reset_control_array_get(node, true, true); | 494 | return of_reset_control_array_get(node, true, true, true); |
| 434 | } | 495 | } |
| 435 | #endif | 496 | #endif |
