regulator: Allow consumer supplies to be set up with dev_name()
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Wed, 17 Jun 2009 16:56:39 +0000 (17:56 +0100)
committerLiam Girdwood <lrg@slimlogic.co.uk>
Tue, 22 Sep 2009 12:32:36 +0000 (13:32 +0100)
Follow the approach suggested by Russell King and implemented by him in
the clkdev API and allow consumer device supply mapings to be set up
using the dev_name() for the consumer instead of the struct device.
In order to avoid making existing machines instabuggy and creating merge
issues the use of struct device is still supported for the time being.

This resolves problems working with buses such as I2C which make the
struct device available late providing that the final device name is
known, which is the case for most embedded systems with fixed setups.

Consumers must still use the struct device when calling regulator_get().

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
drivers/regulator/core.c
include/linux/regulator/machine.h

index 91ba9bfaa706a3a0dfe7ef8679060d0a4df07e00..24e05b7607b4db0974d923cf4792bfe65ba88162 100644 (file)
@@ -37,7 +37,7 @@ static int has_full_constraints;
  */
 struct regulator_map {
        struct list_head list;
-       struct device *dev;
+       const char *dev_name;   /* The dev_name() for the consumer */
        const char *supply;
        struct regulator_dev *regulator;
 };
@@ -857,23 +857,33 @@ out:
  * set_consumer_device_supply: Bind a regulator to a symbolic supply
  * @rdev:         regulator source
  * @consumer_dev: device the supply applies to
+ * @consumer_dev_name: dev_name() string for device supply applies to
  * @supply:       symbolic name for supply
  *
  * Allows platform initialisation code to map physical regulator
  * sources to symbolic names for supplies for use by devices.  Devices
  * should use these symbolic names to request regulators, avoiding the
  * need to provide board-specific regulator names as platform data.
+ *
+ * Only one of consumer_dev and consumer_dev_name may be specified.
  */
 static int set_consumer_device_supply(struct regulator_dev *rdev,
-       struct device *consumer_dev, const char *supply)
+       struct device *consumer_dev, const char *consumer_dev_name,
+       const char *supply)
 {
        struct regulator_map *node;
 
+       if (consumer_dev && consumer_dev_name)
+               return -EINVAL;
+
+       if (!consumer_dev_name && consumer_dev)
+               consumer_dev_name = dev_name(consumer_dev);
+
        if (supply == NULL)
                return -EINVAL;
 
        list_for_each_entry(node, &regulator_map_list, list) {
-               if (consumer_dev != node->dev)
+               if (consumer_dev_name != node->dev_name)
                        continue;
                if (strcmp(node->supply, supply) != 0)
                        continue;
@@ -891,25 +901,38 @@ static int set_consumer_device_supply(struct regulator_dev *rdev,
                return -ENOMEM;
 
        node->regulator = rdev;
-       node->dev = consumer_dev;
+       node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL);
        node->supply = supply;
 
+       if (node->dev_name == NULL) {
+               kfree(node);
+               return -ENOMEM;
+       }
+
        list_add(&node->list, &regulator_map_list);
        return 0;
 }
 
 static void unset_consumer_device_supply(struct regulator_dev *rdev,
-       struct device *consumer_dev)
+       const char *consumer_dev_name, struct device *consumer_dev)
 {
        struct regulator_map *node, *n;
 
+       if (consumer_dev && !consumer_dev_name)
+               consumer_dev_name = dev_name(consumer_dev);
+
        list_for_each_entry_safe(node, n, &regulator_map_list, list) {
-               if (rdev == node->regulator &&
-                       consumer_dev == node->dev) {
-                       list_del(&node->list);
-                       kfree(node);
-                       return;
-               }
+               if (rdev != node->regulator)
+                       continue;
+
+               if (consumer_dev_name && node->dev_name &&
+                   strcmp(consumer_dev_name, node->dev_name))
+                       continue;
+
+               list_del(&node->list);
+               kfree(node->dev_name);
+               kfree(node);
+               return;
        }
 }
 
@@ -920,6 +943,7 @@ static void unset_regulator_supplies(struct regulator_dev *rdev)
        list_for_each_entry_safe(node, n, &regulator_map_list, list) {
                if (rdev == node->regulator) {
                        list_del(&node->list);
+                       kfree(node->dev_name);
                        kfree(node);
                        return;
                }
@@ -1019,17 +1043,25 @@ struct regulator *regulator_get(struct device *dev, const char *id)
        struct regulator_dev *rdev;
        struct regulator_map *map;
        struct regulator *regulator = ERR_PTR(-ENODEV);
+       const char *devname = NULL;
 
        if (id == NULL) {
                printk(KERN_ERR "regulator: get() with no identifier\n");
                return regulator;
        }
 
+       if (dev)
+               devname = dev_name(dev);
+
        mutex_lock(&regulator_list_mutex);
 
        list_for_each_entry(map, &regulator_map_list, list) {
-               if (dev == map->dev &&
-                   strcmp(map->supply, id) == 0) {
+               /* If the mapping has a device set up it must match */
+               if (map->dev_name &&
+                   (!devname || strcmp(map->dev_name, devname)))
+                       continue;
+
+               if (strcmp(map->supply, id) == 0) {
                        rdev = map->regulator;
                        goto found;
                }
@@ -2091,11 +2123,13 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
        for (i = 0; i < init_data->num_consumer_supplies; i++) {
                ret = set_consumer_device_supply(rdev,
                        init_data->consumer_supplies[i].dev,
+                       init_data->consumer_supplies[i].dev_name,
                        init_data->consumer_supplies[i].supply);
                if (ret < 0) {
                        for (--i; i >= 0; i--)
                                unset_consumer_device_supply(rdev,
-                                       init_data->consumer_supplies[i].dev);
+                                   init_data->consumer_supplies[i].dev_name,
+                                   init_data->consumer_supplies[i].dev);
                        goto scrub;
                }
        }
index bac64fa390f20981c1dd8a1fc8b49657bc2ef30b..9328090eca202f5921806b8f9b649cad852c210d 100644 (file)
@@ -126,13 +126,18 @@ struct regulation_constraints {
 /**
  * struct regulator_consumer_supply - supply -> device mapping
  *
- * This maps a supply name to a device.
+ * This maps a supply name to a device.  Only one of dev or dev_name
+ * can be specified.  Use of dev_name allows support for buses which
+ * make struct device available late such as I2C and is the preferred
+ * form.
  *
  * @dev: Device structure for the consumer.
+ * @dev_name: Result of dev_name() for the consumer.
  * @supply: Name for the supply.
  */
 struct regulator_consumer_supply {
        struct device *dev;     /* consumer */
+       const char *dev_name;   /* dev_name() for consumer */
        const char *supply;     /* consumer supply - e.g. "vcc" */
 };
 
This page took 0.051022 seconds and 5 git commands to generate.