summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2016-11-15 04:07:25 -0800
committerGerrit - the friendly Code Review server <code-review@localhost>2016-11-15 04:07:25 -0800
commit4c014824b993b00f29eae7c8b43544d6b739bc85 (patch)
tree2f148fa84826f895965ffd16baac3ca61874f720
parentd05c65bf95abfb889d13c4be599306f1c04110d8 (diff)
parent561bfca197b2870ad3eeec764cce749e11995841 (diff)
Merge "leds: qpnp-flash-v2: Add support for programming led clamp currents"
-rw-r--r--Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt32
-rw-r--r--arch/arm/boot/dts/qcom/msm-pm2falcon.dtsi8
-rw-r--r--arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi8
-rw-r--r--drivers/leds/leds-qpnp-flash-v2.c368
4 files changed, 218 insertions, 198 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..8844a816052e 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt
@@ -32,6 +32,18 @@ Optional properties:
- qcom,vph-droop-debounce-us : Integer property to specify VPH droop debounce time. It is only used
if qcom,vph-droop-det is specified. Valid values are 0, 8, 16 and 26.
Unit is uS.
+- qcom,led1n2-iclamp-low-ma : Integer property to specify current clamp low
+ level for mitigation. Unit is mA. Allowed
+ values are same as under qcom,max-current.
+- qcom,led1n2-iclamp-mid-ma : Integer property to specify current clamp mid
+ level for mitigation. Unit is mA. Allowed
+ values are same as under qcom,max-current.
+- qcom,led3-iclamp-low-ma : Integer property to specify current clamp low
+ level for mitigation. Unit is mA. Allowed
+ values are same as under qcom,max-current.
+- qcom,led3-iclamp-mid-ma : Integer property to specify current clamp mid
+ level for mitigation. Unit is mA. Allowed
+ values are same as under qcom,max-current.
- qcom,vled-max-uv : Integer property for flash current predictive mitigation.
Default value is 3500000 uV.
- qcom,ibatt-ocp-threshold-ua : Integer property for flash current predictive mitigation.
@@ -70,6 +82,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 +140,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 +165,7 @@ Example:
qcom,hdrm-auto-mode;
qcom,isc-delay = <192>;
+ switch0-supply = <&pmicobalt_bob>;
pmi8998_flash0: qcom,flash_0 {
label = "flash";
@@ -254,10 +260,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 +268,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 51fd79f101c8..ea3d0eed47e1 100644
--- a/drivers/leds/leds-qpnp-flash-v2.c
+++ b/drivers/leds/leds-qpnp-flash-v2.c
@@ -49,6 +49,10 @@
#define FLASH_LED_REG_VPH_DROOP_THRESHOLD(base) (base + 0x61)
#define FLASH_LED_REG_VPH_DROOP_DEBOUNCE(base) (base + 0x62)
#define FLASH_LED_REG_ILED_GRT_THRSH(base) (base + 0x67)
+#define FLASH_LED_REG_LED1N2_ICLAMP_LOW(base) (base + 0x68)
+#define FLASH_LED_REG_LED1N2_ICLAMP_MID(base) (base + 0x69)
+#define FLASH_LED_REG_LED3_ICLAMP_LOW(base) (base + 0x6A)
+#define FLASH_LED_REG_LED3_ICLAMP_MID(base) (base + 0x6B)
#define FLASH_LED_REG_MITIGATION_SEL(base) (base + 0x6E)
#define FLASH_LED_REG_MITIGATION_SW(base) (base + 0x6F)
#define FLASH_LED_REG_LMH_LEVEL(base) (base + 0x70)
@@ -173,18 +177,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;
};
@@ -202,6 +200,10 @@ struct flash_led_platform_data {
int rpara_uohm;
int lmh_rbatt_threshold_uohm;
int lmh_ocv_threshold_uv;
+ u32 led1n2_iclamp_low_ma;
+ u32 led1n2_iclamp_mid_ma;
+ u32 led3_iclamp_low_ma;
+ u32 led3_iclamp_mid_ma;
u8 isc_delay;
u8 warmup_delay;
u8 current_derate_en_cfg;
@@ -385,6 +387,46 @@ static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led)
if (rc < 0)
return rc;
+ if (led->pdata->led1n2_iclamp_low_ma) {
+ val = CURRENT_MA_TO_REG_VAL(led->pdata->led1n2_iclamp_low_ma,
+ led->fnode[0].ires_ua);
+ rc = qpnp_flash_led_masked_write(led,
+ FLASH_LED_REG_LED1N2_ICLAMP_LOW(led->base),
+ FLASH_LED_CURRENT_MASK, val);
+ if (rc < 0)
+ return rc;
+ }
+
+ if (led->pdata->led1n2_iclamp_mid_ma) {
+ val = CURRENT_MA_TO_REG_VAL(led->pdata->led1n2_iclamp_mid_ma,
+ led->fnode[0].ires_ua);
+ rc = qpnp_flash_led_masked_write(led,
+ FLASH_LED_REG_LED1N2_ICLAMP_MID(led->base),
+ FLASH_LED_CURRENT_MASK, val);
+ if (rc < 0)
+ return rc;
+ }
+
+ if (led->pdata->led3_iclamp_low_ma) {
+ val = CURRENT_MA_TO_REG_VAL(led->pdata->led3_iclamp_low_ma,
+ led->fnode[3].ires_ua);
+ rc = qpnp_flash_led_masked_write(led,
+ FLASH_LED_REG_LED3_ICLAMP_LOW(led->base),
+ FLASH_LED_CURRENT_MASK, val);
+ if (rc < 0)
+ return rc;
+ }
+
+ if (led->pdata->led3_iclamp_mid_ma) {
+ val = CURRENT_MA_TO_REG_VAL(led->pdata->led3_iclamp_mid_ma,
+ led->fnode[3].ires_ua);
+ rc = qpnp_flash_led_masked_write(led,
+ FLASH_LED_REG_LED3_ICLAMP_MID(led->base),
+ FLASH_LED_CURRENT_MASK, val);
+ if (rc < 0)
+ return rc;
+ }
+
return 0;
}
@@ -426,34 +468,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 +870,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;
}
@@ -1050,6 +1085,32 @@ static void qpnp_flash_led_brightness_set(struct led_classdev *led_cdev,
spin_unlock(&led->lock);
}
+/* sysfs show function for flash_max_current */
+static ssize_t qpnp_flash_led_max_current_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int rc;
+ struct flash_switch_data *snode;
+ struct qpnp_flash_led *led;
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+
+ snode = container_of(led_cdev, struct flash_switch_data, cdev);
+ led = dev_get_drvdata(&snode->pdev->dev);
+
+ rc = qpnp_flash_led_get_max_avail_current(led);
+ if (rc < 0)
+ dev_err(&led->pdev->dev, "query max current failed, rc=%d\n",
+ rc);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", rc);
+}
+
+/* sysfs attributes exported by flash_led */
+static struct device_attribute qpnp_flash_led_attrs[] = {
+ __ATTR(max_current, (S_IRUGO | S_IWUSR | S_IWGRP),
+ qpnp_flash_led_max_current_show, NULL),
+};
+
static int flash_led_psy_notifier_call(struct notifier_block *nb,
unsigned long ev, void *v)
{
@@ -1156,104 +1217,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)
{
@@ -1440,7 +1403,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 =
@@ -1471,7 +1434,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) {
@@ -1480,6 +1444,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) {
@@ -1499,18 +1469,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;
}
}
@@ -1651,6 +1619,42 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led,
return rc;
}
+ rc = of_property_read_u32(node, "qcom,led1n2-iclamp-low-ma", &val);
+ if (!rc) {
+ led->pdata->led1n2_iclamp_low_ma = val;
+ } else if (rc != -EINVAL) {
+ dev_err(&led->pdev->dev, "Unable to read led1n2_iclamp_low current, rc=%d\n",
+ rc);
+ return rc;
+ }
+
+ rc = of_property_read_u32(node, "qcom,led1n2-iclamp-mid-ma", &val);
+ if (!rc) {
+ led->pdata->led1n2_iclamp_mid_ma = val;
+ } else if (rc != -EINVAL) {
+ dev_err(&led->pdev->dev, "Unable to read led1n2_iclamp_mid current, rc=%d\n",
+ rc);
+ return rc;
+ }
+
+ rc = of_property_read_u32(node, "qcom,led3-iclamp-low-ma", &val);
+ if (!rc) {
+ led->pdata->led3_iclamp_low_ma = val;
+ } else if (rc != -EINVAL) {
+ dev_err(&led->pdev->dev, "Unable to read led3_iclamp_low current, rc=%d\n",
+ rc);
+ return rc;
+ }
+
+ rc = of_property_read_u32(node, "qcom,led3-iclamp-mid-ma", &val);
+ if (!rc) {
+ led->pdata->led3_iclamp_mid_ma = val;
+ } else if (rc != -EINVAL) {
+ dev_err(&led->pdev->dev, "Unable to read led3_iclamp_mid current, rc=%d\n",
+ rc);
+ return rc;
+ }
+
led->pdata->vled_max_uv = FLASH_LED_VLED_MAX_DEFAULT_UV;
rc = of_property_read_u32(node, "qcom,vled-max-uv", &val);
if (!rc) {
@@ -1785,7 +1789,7 @@ static int qpnp_flash_led_probe(struct platform_device *pdev)
struct device_node *node, *temp;
const char *temp_string;
unsigned int base;
- int rc, i = 0;
+ int rc, i = 0, j = 0;
node = pdev->dev.of_node;
if (!node) {
@@ -1863,26 +1867,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;
+ }
}
}
@@ -1946,12 +1959,36 @@ static int qpnp_flash_led_probe(struct platform_device *pdev)
goto unreg_notifier;
}
+ for (i = 0; i < led->num_snodes; i++) {
+ for (j = 0; j < ARRAY_SIZE(qpnp_flash_led_attrs); j++) {
+ rc = sysfs_create_file(&led->snode[i].cdev.dev->kobj,
+ &qpnp_flash_led_attrs[j].attr);
+ if (rc < 0) {
+ dev_err(&pdev->dev, "sysfs creation failed, rc=%d\n",
+ rc);
+ goto sysfs_fail;
+ }
+ }
+ }
+
spin_lock_init(&led->lock);
dev_set_drvdata(&pdev->dev, led);
return 0;
+sysfs_fail:
+ for (--j; j >= 0; j--)
+ sysfs_remove_file(&led->snode[i].cdev.dev->kobj,
+ &qpnp_flash_led_attrs[j].attr);
+
+ for (--i; i >= 0; i--) {
+ for (j = 0; j < ARRAY_SIZE(qpnp_flash_led_attrs); j++)
+ sysfs_remove_file(&led->snode[i].cdev.dev->kobj,
+ &qpnp_flash_led_attrs[j].attr);
+ }
+
+ i = led->num_snodes;
unreg_notifier:
power_supply_unreg_notifier(&led->nb);
error_switch_register:
@@ -1968,20 +2005,21 @@ error_led_register:
static int qpnp_flash_led_remove(struct platform_device *pdev)
{
struct qpnp_flash_led *led = dev_get_drvdata(&pdev->dev);
- int i;
+ int i, j;
for (i = 0; i < led->num_snodes; i++) {
- 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,
+ for (j = 0; j < ARRAY_SIZE(qpnp_flash_led_attrs); j++)
+ sysfs_remove_file(&led->snode[i].cdev.dev->kobj,
+ &qpnp_flash_led_attrs[j].attr);
+
+ if (led->snode[i].regulator_on)
+ qpnp_flash_led_regulator_enable(led,
&led->snode[i], false);
- }
}
while (i > 0)
led_classdev_unregister(&led->snode[--i].cdev);
+
i = led->num_fnodes;
while (i > 0)
led_classdev_unregister(&led->fnode[--i].cdev);