From 05939b3db20fa73d54ff39bcb221a1a54b3be58b Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Mon, 24 Oct 2016 20:22:19 -0700 Subject: [PATCH] leds: qpnp-flash-v2: modify regulator control for switch devices 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 --- .../bindings/leds/leds-qpnp-flash-v2.txt | 20 +- arch/arm/boot/dts/qcom/msm-pm2falcon.dtsi | 8 - arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi | 8 - drivers/leds/leds-qpnp-flash-v2.c | 225 ++++++--------------- 4 files changed, 65 insertions(+), 196 deletions(-) diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt b/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt index 8365762e520f..2982cec02023 100644 --- a/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt +++ b/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt @@ -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 : reg ( 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>; - }; }; }; diff --git a/arch/arm/boot/dts/qcom/msm-pm2falcon.dtsi b/arch/arm/boot/dts/qcom/msm-pm2falcon.dtsi index 41589d02f6fc..0e5a999e4642 100644 --- a/arch/arm/boot/dts/qcom/msm-pm2falcon.dtsi +++ b/arch/arm/boot/dts/qcom/msm-pm2falcon.dtsi @@ -357,10 +357,6 @@ 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 { @@ -368,10 +364,6 @@ 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>; - }; }; }; }; diff --git a/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi b/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi index b88b0e28c948..640aa53364a5 100644 --- a/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi +++ b/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi @@ -744,10 +744,6 @@ 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 { @@ -755,10 +751,6 @@ 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>; - }; }; }; }; diff --git a/drivers/leds/leds-qpnp-flash-v2.c b/drivers/leds/leds-qpnp-flash-v2.c index 5129f130d70e..80f1d8af5905 100644 --- a/drivers/leds/leds-qpnp-flash-v2.c +++ b/drivers/leds/leds-qpnp-flash-v2.c @@ -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) -- 2.11.0