regulator: of: add support for adding consumer list from DT
Laxman Dewangan [Tue, 17 Sep 2013 14:45:26 +0000 (19:45 +0530)]
To support the regulator registration through DT and consumer
from non-dt, add support for adding consumer list through DT
so that non-dt driver can get their regulator in normal way
without modifying anything on client driver.

Change-Id: I7d3ca0994b1d5c28767b956df4c3eb861eec2af4
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviewed-on: http://git-master/r/275794

Documentation/devicetree/bindings/regulator/regulator.txt
drivers/regulator/of_regulator.c

index 713f9b2..0fd87f3 100644 (file)
@@ -20,6 +20,27 @@ Deprecated properties:
   this child node is intended to configure. If this property is missing,
   the node's name will be used instead.
 
+Consumer name support from DT:
+To support the consumer list of the rails from DT to map the power tree
+so that driver who uses the regualtor can still be non-dt, adding following
+properties.
+The consumer list will be provided under subnode of each regualtor called
+"consumer". The consumer list has the supply name and device name. This can
+be set with properties:
+regulator-consumer-supply: Consumer supply name.
+regulator-consumer-device: Consumer device name.
+The properties will be passed as
+       consumers {
+               c1 {
+                       regulator-consumer-supply = "vana";
+                       regulator-consumer-device = "2-0010";
+               };
+
+               c2 {
+                       regulator-consumer-supply = "vana";
+                       regulator-consumer-device = "2-0036";
+               };
+
 Example:
 
        xyzreg: regulator@0 {
@@ -61,3 +82,35 @@ regulators (twl_reg1 and twl_reg2),
                vmmc-supply = <&twl_reg1>;
                vmmcaux-supply = <&twl_reg2>;
        };
+
+
+Example: Consumer list from DT
+       ldo3 {
+               regulator-name = "vdd_rtc";
+               regulator-min-microvolt = <800000>;
+               regulator-max-microvolt = <800000>;
+               regulator-always-on;
+               ams,enable-tracking;
+               consumers {
+                       c1 {
+                               regulator-consumer-supply = "vdd_rtc";
+                       };
+               };
+       };
+
+       ldo4 {
+               regulator-name = "avdd_cam";
+               regulator-min-microvolt = <2700000>;
+               regulator-max-microvolt = <2700000>;
+               regulator-always-on;
+               consumers {
+                       c1 {
+                               regulator-consumer-supply = "vana";
+                               regulator-consumer-device = "2-0010";
+                       };
+                       c2 {
+                               regulator-consumer-supply = "vana";
+                               regulator-consumer-device = "2-0036";
+                       };
+               };
+       };
index 3695d72..3b6e2cf 100644 (file)
 #include <linux/regulator/machine.h>
 #include <linux/regulator/of_regulator.h>
 
+static void of_get_regulator_consumer_list(struct device *dev,
+               struct device_node *np,
+               struct regulator_consumer_supply **consumer_list,
+               int *num_consumer)
+{
+       struct device_node *np_consumer;
+       struct device_node *child;
+       int n_consumer;
+       struct regulator_consumer_supply *consumer;
+       int ncount;
+       int ret;
+
+       *consumer_list = NULL;
+       *num_consumer = 0;
+
+       np_consumer = of_get_child_by_name(np, "consumers");
+       if (!np_consumer)
+               return;
+
+       n_consumer = of_get_child_count(np_consumer);
+       if (!n_consumer)
+               return;
+
+       consumer = devm_kzalloc(dev, n_consumer * sizeof(*consumer),
+                       GFP_KERNEL);
+       if (!consumer) {
+               dev_err(dev, "Memory allocation failed\n");
+               return;
+       }
+
+       ncount = 0;
+       for_each_child_of_node(np_consumer, child) {
+               ret = of_property_read_string(child,
+                               "regulator-consumer-supply",
+                               &consumer[ncount].supply);
+               if (ret < 0) {
+                       dev_err(dev, "Consumer %s does not have supply\n",
+                               child->name);
+                       continue;
+               }
+               ret = of_property_read_string(child,
+                               "regulator-consumer-device",
+                               &consumer[ncount].dev_name);
+               if (ret < 0)
+                       dev_warn(dev, "Consumer %s does not have device name\n",
+                                       child->name);
+               ncount++;
+       }
+       *consumer_list = consumer;
+       *num_consumer = ncount;
+}
+
 static void of_get_regulation_constraints(struct device_node *np,
                                        struct regulator_init_data **init_data)
 {
@@ -91,6 +143,10 @@ struct regulator_init_data *of_get_regulator_init_data(struct device *dev,
                return NULL; /* Out of memory? */
 
        of_get_regulation_constraints(node, &init_data);
+       of_get_regulator_consumer_list(dev, node, &init_data->consumer_supplies,
+                                       &init_data->num_consumer_supplies);
+       dev_dbg(dev, "Adding %d consumers for node %s\n",
+                       init_data->num_consumer_supplies, node->name);
        return init_data;
 }
 EXPORT_SYMBOL_GPL(of_get_regulator_init_data);