diff options
author | Mark Brown <broonie@kernel.org> | 2017-02-19 11:40:23 -0500 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2017-02-19 11:40:23 -0500 |
commit | 401c42429caa8e374d17abcbc92505dd6b2e2a18 (patch) | |
tree | 40786a3839b4f80ab99af02f438cdfc2b9824ff5 | |
parent | 0fe3f971fc83bfd709b70f8ac822ad6db4a05c9e (diff) | |
parent | a4d7641fa797b523c0789d2fa55b0a3d53abc2fb (diff) |
Merge remote-tracking branch 'regulator/topic/core' into regulator-next
-rw-r--r-- | drivers/regulator/core.c | 145 | ||||
-rw-r--r-- | drivers/regulator/devres.c | 66 | ||||
-rw-r--r-- | drivers/regulator/internal.h | 10 |
3 files changed, 110 insertions, 111 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index e9fd40ecaef5..6ea646466a07 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c | |||
@@ -1455,12 +1455,14 @@ static struct regulator_dev *regulator_lookup_by_name(const char *name) | |||
1455 | * lookup could succeed in the future. | 1455 | * lookup could succeed in the future. |
1456 | * | 1456 | * |
1457 | * If successful, returns a struct regulator_dev that corresponds to the name | 1457 | * If successful, returns a struct regulator_dev that corresponds to the name |
1458 | * @supply and with the embedded struct device refcount incremented by one, | 1458 | * @supply and with the embedded struct device refcount incremented by one. |
1459 | * or NULL on failure. The refcount must be dropped by calling put_device(). | 1459 | * The refcount must be dropped by calling put_device(). |
1460 | * On failure one of the following ERR-PTR-encoded values is returned: | ||
1461 | * -ENODEV if lookup fails permanently, -EPROBE_DEFER if lookup could succeed | ||
1462 | * in the future. | ||
1460 | */ | 1463 | */ |
1461 | static struct regulator_dev *regulator_dev_lookup(struct device *dev, | 1464 | static struct regulator_dev *regulator_dev_lookup(struct device *dev, |
1462 | const char *supply, | 1465 | const char *supply) |
1463 | int *ret) | ||
1464 | { | 1466 | { |
1465 | struct regulator_dev *r; | 1467 | struct regulator_dev *r; |
1466 | struct device_node *node; | 1468 | struct device_node *node; |
@@ -1476,16 +1478,12 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev, | |||
1476 | r = of_find_regulator_by_node(node); | 1478 | r = of_find_regulator_by_node(node); |
1477 | if (r) | 1479 | if (r) |
1478 | return r; | 1480 | return r; |
1479 | *ret = -EPROBE_DEFER; | 1481 | |
1480 | return NULL; | ||
1481 | } else { | ||
1482 | /* | 1482 | /* |
1483 | * If we couldn't even get the node then it's | 1483 | * We have a node, but there is no device. |
1484 | * not just that the device didn't register | 1484 | * assume it has not registered yet. |
1485 | * yet, there's no node and we'll never | ||
1486 | * succeed. | ||
1487 | */ | 1485 | */ |
1488 | *ret = -ENODEV; | 1486 | return ERR_PTR(-EPROBE_DEFER); |
1489 | } | 1487 | } |
1490 | } | 1488 | } |
1491 | 1489 | ||
@@ -1506,13 +1504,16 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev, | |||
1506 | 1504 | ||
1507 | if (strcmp(map->supply, supply) == 0 && | 1505 | if (strcmp(map->supply, supply) == 0 && |
1508 | get_device(&map->regulator->dev)) { | 1506 | get_device(&map->regulator->dev)) { |
1509 | mutex_unlock(®ulator_list_mutex); | 1507 | r = map->regulator; |
1510 | return map->regulator; | 1508 | break; |
1511 | } | 1509 | } |
1512 | } | 1510 | } |
1513 | mutex_unlock(®ulator_list_mutex); | 1511 | mutex_unlock(®ulator_list_mutex); |
1514 | 1512 | ||
1515 | return NULL; | 1513 | if (r) |
1514 | return r; | ||
1515 | |||
1516 | return ERR_PTR(-ENODEV); | ||
1516 | } | 1517 | } |
1517 | 1518 | ||
1518 | static int regulator_resolve_supply(struct regulator_dev *rdev) | 1519 | static int regulator_resolve_supply(struct regulator_dev *rdev) |
@@ -1529,8 +1530,10 @@ static int regulator_resolve_supply(struct regulator_dev *rdev) | |||
1529 | if (rdev->supply) | 1530 | if (rdev->supply) |
1530 | return 0; | 1531 | return 0; |
1531 | 1532 | ||
1532 | r = regulator_dev_lookup(dev, rdev->supply_name, &ret); | 1533 | r = regulator_dev_lookup(dev, rdev->supply_name); |
1533 | if (!r) { | 1534 | if (IS_ERR(r)) { |
1535 | ret = PTR_ERR(r); | ||
1536 | |||
1534 | if (ret == -ENODEV) { | 1537 | if (ret == -ENODEV) { |
1535 | /* | 1538 | /* |
1536 | * No supply was specified for this regulator and | 1539 | * No supply was specified for this regulator and |
@@ -1580,69 +1583,72 @@ static int regulator_resolve_supply(struct regulator_dev *rdev) | |||
1580 | } | 1583 | } |
1581 | 1584 | ||
1582 | /* Internal regulator request function */ | 1585 | /* Internal regulator request function */ |
1583 | static struct regulator *_regulator_get(struct device *dev, const char *id, | 1586 | struct regulator *_regulator_get(struct device *dev, const char *id, |
1584 | bool exclusive, bool allow_dummy) | 1587 | enum regulator_get_type get_type) |
1585 | { | 1588 | { |
1586 | struct regulator_dev *rdev; | 1589 | struct regulator_dev *rdev; |
1587 | struct regulator *regulator = ERR_PTR(-EPROBE_DEFER); | 1590 | struct regulator *regulator; |
1588 | const char *devname = NULL; | 1591 | const char *devname = dev ? dev_name(dev) : "deviceless"; |
1589 | int ret; | 1592 | int ret; |
1590 | 1593 | ||
1594 | if (get_type >= MAX_GET_TYPE) { | ||
1595 | dev_err(dev, "invalid type %d in %s\n", get_type, __func__); | ||
1596 | return ERR_PTR(-EINVAL); | ||
1597 | } | ||
1598 | |||
1591 | if (id == NULL) { | 1599 | if (id == NULL) { |
1592 | pr_err("get() with no identifier\n"); | 1600 | pr_err("get() with no identifier\n"); |
1593 | return ERR_PTR(-EINVAL); | 1601 | return ERR_PTR(-EINVAL); |
1594 | } | 1602 | } |
1595 | 1603 | ||
1596 | if (dev) | 1604 | rdev = regulator_dev_lookup(dev, id); |
1597 | devname = dev_name(dev); | 1605 | if (IS_ERR(rdev)) { |
1598 | 1606 | ret = PTR_ERR(rdev); | |
1599 | if (have_full_constraints()) | ||
1600 | ret = -ENODEV; | ||
1601 | else | ||
1602 | ret = -EPROBE_DEFER; | ||
1603 | |||
1604 | rdev = regulator_dev_lookup(dev, id, &ret); | ||
1605 | if (rdev) | ||
1606 | goto found; | ||
1607 | 1607 | ||
1608 | regulator = ERR_PTR(ret); | 1608 | /* |
1609 | * If regulator_dev_lookup() fails with error other | ||
1610 | * than -ENODEV our job here is done, we simply return it. | ||
1611 | */ | ||
1612 | if (ret != -ENODEV) | ||
1613 | return ERR_PTR(ret); | ||
1609 | 1614 | ||
1610 | /* | 1615 | if (!have_full_constraints()) { |
1611 | * If we have return value from dev_lookup fail, we do not expect to | 1616 | dev_warn(dev, |
1612 | * succeed, so, quit with appropriate error value | 1617 | "incomplete constraints, dummy supplies not allowed\n"); |
1613 | */ | 1618 | return ERR_PTR(-ENODEV); |
1614 | if (ret && ret != -ENODEV) | 1619 | } |
1615 | return regulator; | ||
1616 | 1620 | ||
1617 | if (!devname) | 1621 | switch (get_type) { |
1618 | devname = "deviceless"; | 1622 | case NORMAL_GET: |
1623 | /* | ||
1624 | * Assume that a regulator is physically present and | ||
1625 | * enabled, even if it isn't hooked up, and just | ||
1626 | * provide a dummy. | ||
1627 | */ | ||
1628 | dev_warn(dev, | ||
1629 | "%s supply %s not found, using dummy regulator\n", | ||
1630 | devname, id); | ||
1631 | rdev = dummy_regulator_rdev; | ||
1632 | get_device(&rdev->dev); | ||
1633 | break; | ||
1619 | 1634 | ||
1620 | /* | 1635 | case EXCLUSIVE_GET: |
1621 | * Assume that a regulator is physically present and enabled | 1636 | dev_warn(dev, |
1622 | * even if it isn't hooked up and just provide a dummy. | 1637 | "dummy supplies not allowed for exclusive requests\n"); |
1623 | */ | 1638 | /* fall through */ |
1624 | if (have_full_constraints() && allow_dummy) { | ||
1625 | pr_warn("%s supply %s not found, using dummy regulator\n", | ||
1626 | devname, id); | ||
1627 | 1639 | ||
1628 | rdev = dummy_regulator_rdev; | 1640 | default: |
1629 | get_device(&rdev->dev); | 1641 | return ERR_PTR(-ENODEV); |
1630 | goto found; | 1642 | } |
1631 | /* Don't log an error when called from regulator_get_optional() */ | ||
1632 | } else if (!have_full_constraints() || exclusive) { | ||
1633 | dev_warn(dev, "dummy supplies not allowed\n"); | ||
1634 | } | 1643 | } |
1635 | 1644 | ||
1636 | return regulator; | ||
1637 | |||
1638 | found: | ||
1639 | if (rdev->exclusive) { | 1645 | if (rdev->exclusive) { |
1640 | regulator = ERR_PTR(-EPERM); | 1646 | regulator = ERR_PTR(-EPERM); |
1641 | put_device(&rdev->dev); | 1647 | put_device(&rdev->dev); |
1642 | return regulator; | 1648 | return regulator; |
1643 | } | 1649 | } |
1644 | 1650 | ||
1645 | if (exclusive && rdev->open_count) { | 1651 | if (get_type == EXCLUSIVE_GET && rdev->open_count) { |
1646 | regulator = ERR_PTR(-EBUSY); | 1652 | regulator = ERR_PTR(-EBUSY); |
1647 | put_device(&rdev->dev); | 1653 | put_device(&rdev->dev); |
1648 | return regulator; | 1654 | return regulator; |
@@ -1656,6 +1662,7 @@ found: | |||
1656 | } | 1662 | } |
1657 | 1663 | ||
1658 | if (!try_module_get(rdev->owner)) { | 1664 | if (!try_module_get(rdev->owner)) { |
1665 | regulator = ERR_PTR(-EPROBE_DEFER); | ||
1659 | put_device(&rdev->dev); | 1666 | put_device(&rdev->dev); |
1660 | return regulator; | 1667 | return regulator; |
1661 | } | 1668 | } |
@@ -1669,7 +1676,7 @@ found: | |||
1669 | } | 1676 | } |
1670 | 1677 | ||
1671 | rdev->open_count++; | 1678 | rdev->open_count++; |
1672 | if (exclusive) { | 1679 | if (get_type == EXCLUSIVE_GET) { |
1673 | rdev->exclusive = 1; | 1680 | rdev->exclusive = 1; |
1674 | 1681 | ||
1675 | ret = _regulator_is_enabled(rdev); | 1682 | ret = _regulator_is_enabled(rdev); |
@@ -1697,7 +1704,7 @@ found: | |||
1697 | */ | 1704 | */ |
1698 | struct regulator *regulator_get(struct device *dev, const char *id) | 1705 | struct regulator *regulator_get(struct device *dev, const char *id) |
1699 | { | 1706 | { |
1700 | return _regulator_get(dev, id, false, true); | 1707 | return _regulator_get(dev, id, NORMAL_GET); |
1701 | } | 1708 | } |
1702 | EXPORT_SYMBOL_GPL(regulator_get); | 1709 | EXPORT_SYMBOL_GPL(regulator_get); |
1703 | 1710 | ||
@@ -1724,7 +1731,7 @@ EXPORT_SYMBOL_GPL(regulator_get); | |||
1724 | */ | 1731 | */ |
1725 | struct regulator *regulator_get_exclusive(struct device *dev, const char *id) | 1732 | struct regulator *regulator_get_exclusive(struct device *dev, const char *id) |
1726 | { | 1733 | { |
1727 | return _regulator_get(dev, id, true, false); | 1734 | return _regulator_get(dev, id, EXCLUSIVE_GET); |
1728 | } | 1735 | } |
1729 | EXPORT_SYMBOL_GPL(regulator_get_exclusive); | 1736 | EXPORT_SYMBOL_GPL(regulator_get_exclusive); |
1730 | 1737 | ||
@@ -1750,7 +1757,7 @@ EXPORT_SYMBOL_GPL(regulator_get_exclusive); | |||
1750 | */ | 1757 | */ |
1751 | struct regulator *regulator_get_optional(struct device *dev, const char *id) | 1758 | struct regulator *regulator_get_optional(struct device *dev, const char *id) |
1752 | { | 1759 | { |
1753 | return _regulator_get(dev, id, false, false); | 1760 | return _regulator_get(dev, id, OPTIONAL_GET); |
1754 | } | 1761 | } |
1755 | EXPORT_SYMBOL_GPL(regulator_get_optional); | 1762 | EXPORT_SYMBOL_GPL(regulator_get_optional); |
1756 | 1763 | ||
@@ -3660,7 +3667,7 @@ err: | |||
3660 | for (++i; i < num_consumers; ++i) { | 3667 | for (++i; i < num_consumers; ++i) { |
3661 | r = regulator_enable(consumers[i].consumer); | 3668 | r = regulator_enable(consumers[i].consumer); |
3662 | if (r != 0) | 3669 | if (r != 0) |
3663 | pr_err("Failed to reename %s: %d\n", | 3670 | pr_err("Failed to re-enable %s: %d\n", |
3664 | consumers[i].supply, r); | 3671 | consumers[i].supply, r); |
3665 | } | 3672 | } |
3666 | 3673 | ||
@@ -3686,21 +3693,17 @@ int regulator_bulk_force_disable(int num_consumers, | |||
3686 | struct regulator_bulk_data *consumers) | 3693 | struct regulator_bulk_data *consumers) |
3687 | { | 3694 | { |
3688 | int i; | 3695 | int i; |
3689 | int ret; | 3696 | int ret = 0; |
3690 | 3697 | ||
3691 | for (i = 0; i < num_consumers; i++) | 3698 | for (i = 0; i < num_consumers; i++) { |
3692 | consumers[i].ret = | 3699 | consumers[i].ret = |
3693 | regulator_force_disable(consumers[i].consumer); | 3700 | regulator_force_disable(consumers[i].consumer); |
3694 | 3701 | ||
3695 | for (i = 0; i < num_consumers; i++) { | 3702 | /* Store first error for reporting */ |
3696 | if (consumers[i].ret != 0) { | 3703 | if (consumers[i].ret && !ret) |
3697 | ret = consumers[i].ret; | 3704 | ret = consumers[i].ret; |
3698 | goto out; | ||
3699 | } | ||
3700 | } | 3705 | } |
3701 | 3706 | ||
3702 | return 0; | ||
3703 | out: | ||
3704 | return ret; | 3707 | return ret; |
3705 | } | 3708 | } |
3706 | EXPORT_SYMBOL_GPL(regulator_bulk_force_disable); | 3709 | EXPORT_SYMBOL_GPL(regulator_bulk_force_disable); |
diff --git a/drivers/regulator/devres.c b/drivers/regulator/devres.c index 6ec1d400adae..784e3bf32210 100644 --- a/drivers/regulator/devres.c +++ b/drivers/regulator/devres.c | |||
@@ -19,12 +19,6 @@ | |||
19 | 19 | ||
20 | #include "internal.h" | 20 | #include "internal.h" |
21 | 21 | ||
22 | enum { | ||
23 | NORMAL_GET, | ||
24 | EXCLUSIVE_GET, | ||
25 | OPTIONAL_GET, | ||
26 | }; | ||
27 | |||
28 | static void devm_regulator_release(struct device *dev, void *res) | 22 | static void devm_regulator_release(struct device *dev, void *res) |
29 | { | 23 | { |
30 | regulator_put(*(struct regulator **)res); | 24 | regulator_put(*(struct regulator **)res); |
@@ -39,20 +33,7 @@ static struct regulator *_devm_regulator_get(struct device *dev, const char *id, | |||
39 | if (!ptr) | 33 | if (!ptr) |
40 | return ERR_PTR(-ENOMEM); | 34 | return ERR_PTR(-ENOMEM); |
41 | 35 | ||
42 | switch (get_type) { | 36 | regulator = _regulator_get(dev, id, get_type); |
43 | case NORMAL_GET: | ||
44 | regulator = regulator_get(dev, id); | ||
45 | break; | ||
46 | case EXCLUSIVE_GET: | ||
47 | regulator = regulator_get_exclusive(dev, id); | ||
48 | break; | ||
49 | case OPTIONAL_GET: | ||
50 | regulator = regulator_get_optional(dev, id); | ||
51 | break; | ||
52 | default: | ||
53 | regulator = ERR_PTR(-EINVAL); | ||
54 | } | ||
55 | |||
56 | if (!IS_ERR(regulator)) { | 37 | if (!IS_ERR(regulator)) { |
57 | *ptr = regulator; | 38 | *ptr = regulator; |
58 | devres_add(dev, ptr); | 39 | devres_add(dev, ptr); |
@@ -139,6 +120,18 @@ void devm_regulator_put(struct regulator *regulator) | |||
139 | } | 120 | } |
140 | EXPORT_SYMBOL_GPL(devm_regulator_put); | 121 | EXPORT_SYMBOL_GPL(devm_regulator_put); |
141 | 122 | ||
123 | struct regulator_bulk_devres { | ||
124 | struct regulator_bulk_data *consumers; | ||
125 | int num_consumers; | ||
126 | }; | ||
127 | |||
128 | static void devm_regulator_bulk_release(struct device *dev, void *res) | ||
129 | { | ||
130 | struct regulator_bulk_devres *devres = res; | ||
131 | |||
132 | regulator_bulk_free(devres->num_consumers, devres->consumers); | ||
133 | } | ||
134 | |||
142 | /** | 135 | /** |
143 | * devm_regulator_bulk_get - managed get multiple regulator consumers | 136 | * devm_regulator_bulk_get - managed get multiple regulator consumers |
144 | * | 137 | * |
@@ -157,29 +150,22 @@ EXPORT_SYMBOL_GPL(devm_regulator_put); | |||
157 | int devm_regulator_bulk_get(struct device *dev, int num_consumers, | 150 | int devm_regulator_bulk_get(struct device *dev, int num_consumers, |
158 | struct regulator_bulk_data *consumers) | 151 | struct regulator_bulk_data *consumers) |
159 | { | 152 | { |
160 | int i; | 153 | struct regulator_bulk_devres *devres; |
161 | int ret; | 154 | int ret; |
162 | 155 | ||
163 | for (i = 0; i < num_consumers; i++) | 156 | devres = devres_alloc(devm_regulator_bulk_release, |
164 | consumers[i].consumer = NULL; | 157 | sizeof(*devres), GFP_KERNEL); |
165 | 158 | if (!devres) | |
166 | for (i = 0; i < num_consumers; i++) { | 159 | return -ENOMEM; |
167 | consumers[i].consumer = devm_regulator_get(dev, | ||
168 | consumers[i].supply); | ||
169 | if (IS_ERR(consumers[i].consumer)) { | ||
170 | ret = PTR_ERR(consumers[i].consumer); | ||
171 | dev_err(dev, "Failed to get supply '%s': %d\n", | ||
172 | consumers[i].supply, ret); | ||
173 | consumers[i].consumer = NULL; | ||
174 | goto err; | ||
175 | } | ||
176 | } | ||
177 | |||
178 | return 0; | ||
179 | 160 | ||
180 | err: | 161 | ret = regulator_bulk_get(dev, num_consumers, consumers); |
181 | for (i = 0; i < num_consumers && consumers[i].consumer; i++) | 162 | if (!ret) { |
182 | devm_regulator_put(consumers[i].consumer); | 163 | devres->consumers = consumers; |
164 | devres->num_consumers = num_consumers; | ||
165 | devres_add(dev, devres); | ||
166 | } else { | ||
167 | devres_free(devres); | ||
168 | } | ||
183 | 169 | ||
184 | return ret; | 170 | return ret; |
185 | } | 171 | } |
diff --git a/drivers/regulator/internal.h b/drivers/regulator/internal.h index c74ac8734023..1dd575b28564 100644 --- a/drivers/regulator/internal.h +++ b/drivers/regulator/internal.h | |||
@@ -51,4 +51,14 @@ regulator_of_get_init_data(struct device *dev, | |||
51 | } | 51 | } |
52 | #endif | 52 | #endif |
53 | 53 | ||
54 | enum regulator_get_type { | ||
55 | NORMAL_GET, | ||
56 | EXCLUSIVE_GET, | ||
57 | OPTIONAL_GET, | ||
58 | MAX_GET_TYPE | ||
59 | }; | ||
60 | |||
61 | struct regulator *_regulator_get(struct device *dev, const char *id, | ||
62 | enum regulator_get_type get_type); | ||
63 | |||
54 | #endif | 64 | #endif |