OSDN Git Service

leds: qpnp-flash-v2: modify regulator control for switch devices
authorSubbaraman Narayanamurthy <subbaram@codeaurora.org>
Tue, 25 Oct 2016 03:22:19 +0000 (20:22 -0700)
committerSubbaraman Narayanamurthy <subbaram@codeaurora.org>
Fri, 11 Nov 2016 19:59:15 +0000 (11:59 -0800)
Currently multiple regulator devices can be specified for LED
switch device though a switch device may just require one supply.
Also, before the switch device is enabled, voltage request is
sent to set the maximum voltage. This is not needed with the
regulators like BoB being used as supply for the switch device.
Just enabling the regulator is enough during switch operation.
Modify the way the regulator is obtained and controlled for
switch operation.

Since BoB regulator is configured by the bootloader properly
for flash operation, remove them from the supply list of LED
switch devices on pmicobalt and pm2falcon.

While at it, fix the way device tree properties are read from
flash/torch, switch devices.

CRs-Fixed: 1083246
Change-Id: I8eb5f305f89bc18ad4b735bd89cbf259f0e1ea11
Signed-off-by: Subbaraman Narayanamurthy <subbaram@codeaurora.org>
Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt
arch/arm/boot/dts/qcom/msm-pm2falcon.dtsi
arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi
drivers/leds/leds-qpnp-flash-v2.c

index 8365762..2982cec 100644 (file)
@@ -70,6 +70,8 @@ Optional properties:
                          0: Flash strobe is used for LED1, LED2, LED3
                          1: Flash strobe is used for LED1, LED2 and GPIO10 is used for LED3
                          2: Flash strobe is used for LED1; GPIO9 is used for LED2; GPIO10 is used for LED3
+- switchX-supply               : phandle of the regulator that needs to be used
+                                 as a supply for flash switch_X device.
 
 Child node: Contains settings for each individual LED. Each LED channel needs a flash node and
 torch node for itself, and an individual switch node to serve as an overall switch.
@@ -126,15 +128,6 @@ Optional properties:
                                  be edge triggered. Otherwise, it is level triggered.
 - qcom,hw-strobe-active-low    : Boolean property to select strobe signal polarity. If defined, hw-strobe
                                  signal polarity is set to active-low, else it is active-high.
-- reg<n>               : reg<n> (<n> represents number. e.g. 0,1,2,..) subnode is to add support for
-                         multiple power sources. This subnode should only be specified for switch nodes.
-                         Required property inside regulator node:
-                         - regulator-name      : Name of the regulator which has to be used for this
-                                                 switch node.
-                         Optional property inside regulator node:
-                         - max-voltage-uv      : This specifies max voltage of regulator. Some switch
-                                                 or boost regulator does not need this property.
-
 Example:
        qcom,leds@d300 {
                compatible = "qcom,qpnp-flash-led-v2";
@@ -160,6 +153,7 @@ Example:
 
                qcom,hdrm-auto-mode;
                qcom,isc-delay = <192>;
+               switch0-supply = <&pmicobalt_bob>;
 
                pmi8998_flash0: qcom,flash_0 {
                        label = "flash";
@@ -254,10 +248,6 @@ Example:
                        qcom,led-mask = <3>;
                        qcom,default-led-trigger =
                                                "switch0_trigger";
-                       reg0 {
-                               regulator-name = "pmicobalt_bob";
-                               max-voltage-uv = <3600000>;
-                       };
                };
 
                pmi8998_switch1: qcom,led_switch_1 {
@@ -266,10 +256,6 @@ Example:
                        qcom,led-mask = <4>;
                        qcom,default-led-trigger =
                                                "switch1_trigger";
-                       reg0 {
-                               regulator-name = "pmicobalt_bob";
-                               max-voltage-uv = <3600000>;
-                       };
                };
        };
 
index 41589d0..0e5a999 100644 (file)
                                qcom,led-name = "led:switch_0";
                                qcom,led-mask = <3>;
                                qcom,default-led-trigger = "switch0_trigger";
-                               reg0 {
-                                       regulator-name = "pmfalcon_bob";
-                                       max-voltage-uv = <3600000>;
-                               };
                        };
 
                        pm2falcon_switch1: qcom,led_switch_1 {
                                qcom,led-name = "led:switch_1";
                                qcom,led-mask = <4>;
                                qcom,default-led-trigger = "switch1_trigger";
-                               reg0 {
-                                       regulator-name = "pmfalcon_bob";
-                                       max-voltage-uv = <3600000>;
-                               };
                        };
                };
        };
index b88b0e2..640aa53 100644 (file)
                                qcom,led-name = "led:switch_0";
                                qcom,led-mask = <3>;
                                qcom,default-led-trigger = "switch0_trigger";
-                               reg0 {
-                                       regulator-name = "pmicobalt_bob";
-                                       max-voltage-uv = <3600000>;
-                               };
                        };
 
                        pmicobalt_switch1: qcom,led_switch_1 {
                                qcom,led-name = "led:switch_1";
                                qcom,led-mask = <4>;
                                qcom,default-led-trigger = "switch1_trigger";
-                               reg0 {
-                                       regulator-name = "pmicobalt_bob";
-                                       max-voltage-uv = <3600000>;
-                               };
                        };
                };
        };
index 5129f13..80f1d8a 100644 (file)
@@ -173,18 +173,12 @@ struct flash_node_data {
        bool                            led_on;
 };
 
-struct flash_regulator_data {
-       struct regulator                *vreg;
-       const char                      *reg_name;
-       u32                             max_volt_uv;
-};
 
 struct flash_switch_data {
        struct platform_device          *pdev;
+       struct regulator                *vreg;
        struct led_classdev             cdev;
-       struct flash_regulator_data     *reg_data;
        int                             led_mask;
-       int                             num_regulators;
        bool                            regulator_on;
        bool                            enabled;
 };
@@ -426,34 +420,27 @@ static int qpnp_flash_led_hw_strobe_enable(struct flash_node_data *fnode,
 static int qpnp_flash_led_regulator_enable(struct qpnp_flash_led *led,
                                struct flash_switch_data *snode, bool on)
 {
-       int i, rc = 0;
+       int rc = 0;
+
+       if (!snode || !snode->vreg)
+               return 0;
 
        if (snode->regulator_on == on)
                return 0;
 
-       if (on == false) {
-               i = snode->num_regulators;
-               goto out;
-       }
+       if (on)
+               rc = regulator_enable(snode->vreg);
+       else
+               rc = regulator_disable(snode->vreg);
 
-       for (i = 0; i < snode->num_regulators; i++) {
-               rc = regulator_enable(snode->reg_data[i].vreg);
-               if (rc < 0) {
-                       dev_err(&led->pdev->dev,
-                               "regulator enable failed, rc=%d\n", rc);
-                       goto out;
-               }
+       if (rc < 0) {
+               dev_err(&led->pdev->dev, "regulator_%s failed, rc=%d\n",
+                       on ? "enable" : "disable", rc);
+               return rc;
        }
-       snode->regulator_on = true;
 
-       return rc;
-
-out:
-       while (i--)
-               regulator_disable(snode->reg_data[i].vreg);
-
-       snode->regulator_on = false;
-       return rc;
+       snode->regulator_on = on ? true : false;
+       return 0;
 }
 
 static int get_property_from_fg(struct qpnp_flash_led *led,
@@ -835,7 +822,7 @@ static int qpnp_flash_led_switch_set(struct flash_switch_data *snode, bool on)
        u8 val, mask;
 
        if (snode->enabled == on) {
-               dev_warn(&led->pdev->dev, "Switch node is already %s!\n",
+               dev_dbg(&led->pdev->dev, "Switch node is already %s!\n",
                                on ? "enabled" : "disabled");
                return 0;
        }
@@ -1182,104 +1169,6 @@ int qpnp_flash_led_unregister_irq_notifier(struct notifier_block *nb)
        return atomic_notifier_chain_unregister(&irq_notifier_list, nb);
 }
 
-static int qpnp_flash_led_regulator_setup(struct qpnp_flash_led *led,
-                               struct flash_switch_data *snode, bool on)
-{
-       int i, rc = 0;
-
-       if (on == false) {
-               i = snode->num_regulators;
-               goto out;
-       }
-
-       for (i = 0; i < snode->num_regulators; i++) {
-               snode->reg_data[i].vreg = regulator_get(snode->cdev.dev,
-                                               snode->reg_data[i].reg_name);
-               if (IS_ERR(snode->reg_data[i].vreg)) {
-                       rc = PTR_ERR(snode->reg_data[i].vreg);
-                       dev_err(&led->pdev->dev,
-                                       "Failed to get regulator, rc=%d\n", rc);
-                       goto out;
-               }
-
-               if (regulator_count_voltages(snode->reg_data[i].vreg) > 0) {
-                       rc = regulator_set_voltage(snode->reg_data[i].vreg,
-                                       snode->reg_data[i].max_volt_uv,
-                                       snode->reg_data[i].max_volt_uv);
-                       if (rc < 0) {
-                               dev_err(&led->pdev->dev,
-                                       "regulator set voltage failed, rc=%d\n",
-                                       rc);
-                               regulator_put(snode->reg_data[i].vreg);
-                               goto out;
-                       }
-               }
-       }
-
-       return rc;
-
-out:
-       while (i--) {
-               if (regulator_count_voltages(snode->reg_data[i].vreg) > 0)
-                       regulator_set_voltage(snode->reg_data[i].vreg, 0,
-                                       snode->reg_data[i].max_volt_uv);
-
-               regulator_put(snode->reg_data[i].vreg);
-       }
-
-       return rc;
-}
-
-static int qpnp_flash_led_regulator_parse_dt(struct qpnp_flash_led *led,
-                                       struct flash_switch_data *snode,
-                                       struct device_node *node) {
-
-       int i = 0, rc = 0, num_regs = 0;
-       struct device_node *temp = NULL;
-       const char *temp_string;
-       u32 val;
-
-       while ((temp = of_get_next_available_child(node, temp))) {
-               if (of_find_property(temp, "regulator-name", NULL))
-                       num_regs++;
-       }
-       snode->num_regulators = num_regs;
-
-       if (snode->num_regulators == 0)
-               return 0;
-
-       snode->reg_data = devm_kcalloc(&led->pdev->dev, snode->num_regulators,
-                                       sizeof(*snode->reg_data),
-                                       GFP_KERNEL);
-       if (!snode->reg_data)
-               return -ENOMEM;
-
-       for_each_available_child_of_node(node, temp) {
-               rc = of_property_read_string(temp, "regulator-name",
-                                                       &temp_string);
-               if (!rc)
-                       snode->reg_data[i].reg_name = temp_string;
-               else {
-                       dev_err(&led->pdev->dev,
-                               "Unable to read regulator name, rc=%d\n", rc);
-                       return rc;
-               }
-
-               rc = of_property_read_u32(temp, "max-voltage-uv", &val);
-               if (!rc) {
-                       snode->reg_data[i].max_volt_uv = val;
-               } else if (rc != -EINVAL) {
-                       dev_err(&led->pdev->dev,
-                               "Unable to read max voltage, rc=%d\n", rc);
-                       return rc;
-               }
-
-               i++;
-       }
-
-       return 0;
-}
-
 static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
                        struct flash_node_data *fnode, struct device_node *node)
 {
@@ -1466,7 +1355,7 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
 
        fnode->pinctrl = devm_pinctrl_get(fnode->cdev.dev);
        if (IS_ERR_OR_NULL(fnode->pinctrl)) {
-               dev_warn(&led->pdev->dev, "No pinctrl defined\n");
+               dev_dbg(&led->pdev->dev, "No pinctrl defined\n");
                fnode->pinctrl = NULL;
        } else {
                fnode->gpio_state_active =
@@ -1497,7 +1386,8 @@ static int qpnp_flash_led_parse_and_register_switch(struct qpnp_flash_led *led,
                                                struct flash_switch_data *snode,
                                                struct device_node *node)
 {
-       int rc = 0;
+       int rc = 0, num;
+       char reg_name[16], reg_sup_name[16];
 
        rc = of_property_read_string(node, "qcom,led-name", &snode->cdev.name);
        if (rc < 0) {
@@ -1506,6 +1396,12 @@ static int qpnp_flash_led_parse_and_register_switch(struct qpnp_flash_led *led,
                return rc;
        }
 
+       rc = sscanf(snode->cdev.name, "led:switch_%d", &num);
+       if (!rc) {
+               pr_err("No number for switch device?\n");
+               return -EINVAL;
+       }
+
        rc = of_property_read_string(node, "qcom,default-led-trigger",
                                        &snode->cdev.default_trigger);
        if (rc < 0) {
@@ -1525,18 +1421,16 @@ static int qpnp_flash_led_parse_and_register_switch(struct qpnp_flash_led *led,
                return -EINVAL;
        }
 
-       rc = qpnp_flash_led_regulator_parse_dt(led, snode, node);
-       if (rc < 0) {
-               dev_err(&led->pdev->dev,
-                       "Unable to parse regulator data, rc=%d\n", rc);
-               return rc;
-       }
-
-       if (snode->num_regulators) {
-               rc = qpnp_flash_led_regulator_setup(led, snode, true);
-               if (rc < 0) {
-                       dev_err(&led->pdev->dev,
-                               "Unable to setup regulator, rc=%d\n", rc);
+       scnprintf(reg_name, sizeof(reg_name), "switch%d-supply", num);
+       if (of_find_property(led->pdev->dev.of_node, reg_name, NULL)) {
+               scnprintf(reg_sup_name, sizeof(reg_sup_name), "switch%d", num);
+               snode->vreg = devm_regulator_get(&led->pdev->dev, reg_sup_name);
+               if (IS_ERR_OR_NULL(snode->vreg)) {
+                       rc = PTR_ERR(snode->vreg);
+                       if (rc != -EPROBE_DEFER)
+                               dev_err(&led->pdev->dev, "Failed to get regulator, rc=%d\n",
+                                       rc);
+                       snode->vreg = NULL;
                        return rc;
                }
        }
@@ -1889,26 +1783,35 @@ static int qpnp_flash_led_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        temp = NULL;
-       for (i = 0; i < led->num_fnodes; i++) {
-               temp = of_get_next_available_child(node, temp);
-               rc = qpnp_flash_led_parse_each_led_dt(led,
-                                                       &led->fnode[i], temp);
+       i = 0;
+       j = 0;
+       for_each_available_child_of_node(node, temp) {
+               rc = of_property_read_string(temp, "label", &temp_string);
                if (rc < 0) {
                        dev_err(&pdev->dev,
-                               "Unable to parse flash node %d rc=%d\n", i, rc);
-                       goto error_led_register;
+                               "Failed to parse label, rc=%d\n", rc);
+                       return rc;
                }
-       }
 
-       for (i = 0; i < led->num_snodes; i++) {
-               temp = of_get_next_available_child(node, temp);
-               rc = qpnp_flash_led_parse_and_register_switch(led,
-                                                       &led->snode[i], temp);
-               if (rc < 0) {
-                       dev_err(&pdev->dev,
-                               "Unable to parse and register switch node, rc=%d\n",
-                               rc);
-                       goto error_switch_register;
+               if (!strcmp("flash", temp_string) ||
+                               !strcmp("torch", temp_string)) {
+                       rc = qpnp_flash_led_parse_each_led_dt(led,
+                                       &led->fnode[i++], temp);
+                       if (rc < 0) {
+                               dev_err(&pdev->dev, "Unable to parse flash node %d rc=%d\n",
+                                       i, rc);
+                               goto error_led_register;
+                       }
+               }
+
+               if (!strcmp("switch", temp_string)) {
+                       rc = qpnp_flash_led_parse_and_register_switch(led,
+                                       &led->snode[j++], temp);
+                       if (rc < 0) {
+                               dev_err(&pdev->dev, "Unable to parse and register switch node, rc=%d\n",
+                                       rc);
+                               goto error_switch_register;
+                       }
                }
        }
 
@@ -2025,13 +1928,9 @@ static int qpnp_flash_led_remove(struct platform_device *pdev)
                        sysfs_remove_file(&led->snode[i].cdev.dev->kobj,
                                        &qpnp_flash_led_attrs[j].attr);
 
-               if (led->snode[i].num_regulators) {
-                       if (led->snode[i].regulator_on)
-                               qpnp_flash_led_regulator_enable(led,
-                                               &led->snode[i], false);
-                       qpnp_flash_led_regulator_setup(led,
+               if (led->snode[i].regulator_on)
+                       qpnp_flash_led_regulator_enable(led,
                                        &led->snode[i], false);
-               }
        }
 
        while (i > 0)