aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/regulator/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/regulator/core.c')
-rw-r--r--drivers/regulator/core.c170
1 files changed, 170 insertions, 0 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 906deb7354ed..16427de56ce8 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -53,6 +53,7 @@ static DEFINE_MUTEX(regulator_list_mutex);
53static LIST_HEAD(regulator_list); 53static LIST_HEAD(regulator_list);
54static LIST_HEAD(regulator_map_list); 54static LIST_HEAD(regulator_map_list);
55static LIST_HEAD(regulator_ena_gpio_list); 55static LIST_HEAD(regulator_ena_gpio_list);
56static LIST_HEAD(regulator_supply_alias_list);
56static bool has_full_constraints; 57static bool has_full_constraints;
57static bool board_wants_dummy_regulator; 58static bool board_wants_dummy_regulator;
58 59
@@ -83,6 +84,19 @@ struct regulator_enable_gpio {
83 unsigned int ena_gpio_invert:1; 84 unsigned int ena_gpio_invert:1;
84}; 85};
85 86
87/*
88 * struct regulator_supply_alias
89 *
90 * Used to map lookups for a supply onto an alternative device.
91 */
92struct regulator_supply_alias {
93 struct list_head list;
94 struct device *src_dev;
95 const char *src_supply;
96 struct device *alias_dev;
97 const char *alias_supply;
98};
99
86static int _regulator_is_enabled(struct regulator_dev *rdev); 100static int _regulator_is_enabled(struct regulator_dev *rdev);
87static int _regulator_disable(struct regulator_dev *rdev); 101static int _regulator_disable(struct regulator_dev *rdev);
88static int _regulator_get_voltage(struct regulator_dev *rdev); 102static int _regulator_get_voltage(struct regulator_dev *rdev);
@@ -1173,6 +1187,32 @@ static int _regulator_get_enable_time(struct regulator_dev *rdev)
1173 return rdev->desc->ops->enable_time(rdev); 1187 return rdev->desc->ops->enable_time(rdev);
1174} 1188}
1175 1189
1190static struct regulator_supply_alias *regulator_find_supply_alias(
1191 struct device *dev, const char *supply)
1192{
1193 struct regulator_supply_alias *map;
1194
1195 list_for_each_entry(map, &regulator_supply_alias_list, list)
1196 if (map->src_dev == dev && strcmp(map->src_supply, supply) == 0)
1197 return map;
1198
1199 return NULL;
1200}
1201
1202static void regulator_supply_alias(struct device **dev, const char **supply)
1203{
1204 struct regulator_supply_alias *map;
1205
1206 map = regulator_find_supply_alias(*dev, *supply);
1207 if (map) {
1208 dev_dbg(*dev, "Mapping supply %s to %s,%s\n",
1209 *supply, map->alias_supply,
1210 dev_name(map->alias_dev));
1211 *dev = map->alias_dev;
1212 *supply = map->alias_supply;
1213 }
1214}
1215
1176static struct regulator_dev *regulator_dev_lookup(struct device *dev, 1216static struct regulator_dev *regulator_dev_lookup(struct device *dev,
1177 const char *supply, 1217 const char *supply,
1178 int *ret) 1218 int *ret)
@@ -1182,6 +1222,8 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev,
1182 struct regulator_map *map; 1222 struct regulator_map *map;
1183 const char *devname = NULL; 1223 const char *devname = NULL;
1184 1224
1225 regulator_supply_alias(&dev, &supply);
1226
1185 /* first do a dt based lookup */ 1227 /* first do a dt based lookup */
1186 if (dev && dev->of_node) { 1228 if (dev && dev->of_node) {
1187 node = of_get_regulator(dev, supply); 1229 node = of_get_regulator(dev, supply);
@@ -1432,6 +1474,134 @@ void regulator_put(struct regulator *regulator)
1432} 1474}
1433EXPORT_SYMBOL_GPL(regulator_put); 1475EXPORT_SYMBOL_GPL(regulator_put);
1434 1476
1477/**
1478 * regulator_register_supply_alias - Provide device alias for supply lookup
1479 *
1480 * @dev: device that will be given as the regulator "consumer"
1481 * @id: Supply name or regulator ID
1482 * @alias_dev: device that should be used to lookup the supply
1483 * @alias_id: Supply name or regulator ID that should be used to lookup the
1484 * supply
1485 *
1486 * All lookups for id on dev will instead be conducted for alias_id on
1487 * alias_dev.
1488 */
1489int regulator_register_supply_alias(struct device *dev, const char *id,
1490 struct device *alias_dev,
1491 const char *alias_id)
1492{
1493 struct regulator_supply_alias *map;
1494
1495 map = regulator_find_supply_alias(dev, id);
1496 if (map)
1497 return -EEXIST;
1498
1499 map = kzalloc(sizeof(struct regulator_supply_alias), GFP_KERNEL);
1500 if (!map)
1501 return -ENOMEM;
1502
1503 map->src_dev = dev;
1504 map->src_supply = id;
1505 map->alias_dev = alias_dev;
1506 map->alias_supply = alias_id;
1507
1508 list_add(&map->list, &regulator_supply_alias_list);
1509
1510 pr_info("Adding alias for supply %s,%s -> %s,%s\n",
1511 id, dev_name(dev), alias_id, dev_name(alias_dev));
1512
1513 return 0;
1514}
1515EXPORT_SYMBOL_GPL(regulator_register_supply_alias);
1516
1517/**
1518 * regulator_unregister_supply_alias - Remove device alias
1519 *
1520 * @dev: device that will be given as the regulator "consumer"
1521 * @id: Supply name or regulator ID
1522 *
1523 * Remove a lookup alias if one exists for id on dev.
1524 */
1525void regulator_unregister_supply_alias(struct device *dev, const char *id)
1526{
1527 struct regulator_supply_alias *map;
1528
1529 map = regulator_find_supply_alias(dev, id);
1530 if (map) {
1531 list_del(&map->list);
1532 kfree(map);
1533 }
1534}
1535EXPORT_SYMBOL_GPL(regulator_unregister_supply_alias);
1536
1537/**
1538 * regulator_bulk_register_supply_alias - register multiple aliases
1539 *
1540 * @dev: device that will be given as the regulator "consumer"
1541 * @id: List of supply names or regulator IDs
1542 * @alias_dev: device that should be used to lookup the supply
1543 * @alias_id: List of supply names or regulator IDs that should be used to
1544 * lookup the supply
1545 * @num_id: Number of aliases to register
1546 *
1547 * @return 0 on success, an errno on failure.
1548 *
1549 * This helper function allows drivers to register several supply
1550 * aliases in one operation. If any of the aliases cannot be
1551 * registered any aliases that were registered will be removed
1552 * before returning to the caller.
1553 */
1554int regulator_bulk_register_supply_alias(struct device *dev, const char **id,
1555 struct device *alias_dev,
1556 const char **alias_id,
1557 int num_id)
1558{
1559 int i;
1560 int ret;
1561
1562 for (i = 0; i < num_id; ++i) {
1563 ret = regulator_register_supply_alias(dev, id[i], alias_dev,
1564 alias_id[i]);
1565 if (ret < 0)
1566 goto err;
1567 }
1568
1569 return 0;
1570
1571err:
1572 dev_err(dev,
1573 "Failed to create supply alias %s,%s -> %s,%s\n",
1574 id[i], dev_name(dev), alias_id[i], dev_name(alias_dev));
1575
1576 while (--i >= 0)
1577 regulator_unregister_supply_alias(dev, id[i]);
1578
1579 return ret;
1580}
1581EXPORT_SYMBOL_GPL(regulator_bulk_register_supply_alias);
1582
1583/**
1584 * regulator_bulk_unregister_supply_alias - unregister multiple aliases
1585 *
1586 * @dev: device that will be given as the regulator "consumer"
1587 * @id: List of supply names or regulator IDs
1588 * @num_id: Number of aliases to unregister
1589 *
1590 * This helper function allows drivers to unregister several supply
1591 * aliases in one operation.
1592 */
1593void regulator_bulk_unregister_supply_alias(struct device *dev,
1594 const char **id,
1595 int num_id)
1596{
1597 int i;
1598
1599 for (i = 0; i < num_id; ++i)
1600 regulator_unregister_supply_alias(dev, id[i]);
1601}
1602EXPORT_SYMBOL_GPL(regulator_bulk_unregister_supply_alias);
1603
1604
1435/* Manage enable GPIO list. Same GPIO pin can be shared among regulators */ 1605/* Manage enable GPIO list. Same GPIO pin can be shared among regulators */
1436static int regulator_ena_gpio_request(struct regulator_dev *rdev, 1606static int regulator_ena_gpio_request(struct regulator_dev *rdev,
1437 const struct regulator_config *config) 1607 const struct regulator_config *config)