Loading Documentation/devicetree/bindings/leds/leds-qpnp-flash.txt +19 −6 Original line number Diff line number Diff line Loading @@ -90,13 +90,18 @@ operational simplification. For backward compatibility purpose, switch node can Optional properties inside child node: - qcom,current : default current intensity for LED. Accepted values should be integer from 0 t 1000 inclusive, indicating 0 to 1000 mA. - boost-supply : flash LED boost power source for flash LED - boost-voltage-max : maximum voltage for flash LED boost regulator in uV. This attribute is required if boost-supply is defined. - qcom,duration : Duration for flash LED. When duration time expires, hardware will turn off flash LED. Values should be from 10 ms to 1280 ms with 10 ms incremental step. Not applicable to torch. It is required for LED:SWITCH node to handle LED used as flash. - reg<n> : reg<n> (<n> represents number. eg 0,1,2,..) property is to add support for multiple power sources. It includes two properties regulator-name and max-voltage. Required property inside regulator node: - regulator-name : This denotes this node is a regulator node and which regulator to use. Optional property inside regulator node: - max-voltage : This specifies max voltage of regulator. Some switch or boost regulator does not need this property. Example: qcom,leds@d300 { Loading Loading @@ -145,7 +150,12 @@ Example: qcom,max-current = <200>; qcom,id = <0>; qcom,current = <120>; boost-voltage-max = <3600000>; qcom,max-current = <200>; reg0 { regulator-name = "pm8226_chg_boost"; max-voltage = <3600000>; }; }; pm8226_switch: qcom,switch { Loading @@ -157,8 +167,11 @@ Example: qcom,current = <625>; qcom,duration = <1280>; qcom,max-current = <1000>; boost-supply = <pm8226_chg_boost>; boost-voltage-max = <3600000>; reg0 { regulator-name = "pm8226_chg_boost"; max-voltage = <3600000>; }; }; }; drivers/leds/leds-qpnp-flash.c +178 −78 Original line number Diff line number Diff line Loading @@ -163,16 +163,20 @@ enum current_ramp_steps { RAMP_STEP_27US, }; struct flash_regulator_data { struct regulator *regs; const char *reg_name; u32 max_volt_uv; }; /* * Configurations for each individual LED */ struct flash_node_data { struct spmi_device *spmi_dev; struct led_classdev cdev; struct regulator *boost_regulator; struct work_struct work; struct delayed_work dwork; u32 boost_voltage_max; struct flash_regulator_data *reg_data; u16 max_current; u16 prgm_current; u16 prgm_current2; Loading @@ -181,6 +185,7 @@ struct flash_node_data { u8 type; u8 trigger; u8 enable; u8 num_regulators; bool flash_on; }; Loading Loading @@ -1002,6 +1007,131 @@ led_brightness qpnp_flash_led_brightness_get(struct led_classdev *led_cdev) return led_cdev->brightness; } static int flash_regulator_parse_dt(struct qpnp_flash_led *led, struct flash_node_data *flash_node) { int i = 0, rc; struct device_node *node = flash_node->cdev.dev->of_node; struct device_node *temp = NULL; const char *temp_string; u32 val; flash_node->reg_data = devm_kzalloc(&led->spmi_dev->dev, sizeof(struct flash_regulator_data *) * flash_node->num_regulators, GFP_KERNEL); if (!flash_node->reg_data) { dev_err(&led->spmi_dev->dev, "Unable to allocate memory\n"); return -ENOMEM; } for_each_child_of_node(node, temp) { rc = of_property_read_string(temp, "regulator-name", &temp_string); if (!rc) flash_node->reg_data[i].reg_name = temp_string; else { dev_err(&led->spmi_dev->dev, "Unable to read regulator name\n"); return rc; } if (of_find_property(temp, "max-voltage", NULL)) { rc = of_property_read_u32(temp, "max-voltage", &val); if (!rc) { flash_node->reg_data[i].max_volt_uv = val; } else { dev_err(&led->spmi_dev->dev, "Unable to read max voltage\n"); return rc; } } i++; } return rc; } static int flash_regulator_setup(struct qpnp_flash_led *led, struct flash_node_data *flash_node, bool on) { int i, rc = 0; if (on == false) { i = flash_node->num_regulators; goto error_regulator_setup; } for (i = 0; i < flash_node->num_regulators; i++) { flash_node->reg_data[i].regs = regulator_get(flash_node->cdev.dev, flash_node->reg_data[i].reg_name); if (IS_ERR(flash_node->reg_data[i].regs)) { rc = PTR_ERR(flash_node->reg_data[i].regs); dev_err(&led->spmi_dev->dev, "Failed to get regulator\n"); goto error_regulator_setup; } if (regulator_count_voltages(flash_node->reg_data[i].regs) > 0) { rc = regulator_set_voltage(flash_node->reg_data[i].regs, flash_node->reg_data[i].max_volt_uv, flash_node->reg_data[i].max_volt_uv); if (rc) { dev_err(&led->spmi_dev->dev, "regulator set voltage failed\n"); regulator_put(flash_node->reg_data[i].regs); goto error_regulator_setup; } } } return rc; error_regulator_setup: while (i--) { if (regulator_count_voltages(flash_node->reg_data[i].regs) > 0) { regulator_set_voltage(flash_node->reg_data[i].regs, 0, flash_node->reg_data[i].max_volt_uv); } regulator_put(flash_node->reg_data[i].regs); } return rc; } static int flash_regulator_enable(struct qpnp_flash_led *led, struct flash_node_data *flash_node, bool on) { int i, rc = 0; if (on == false) { i = flash_node->num_regulators; goto error_regulator_enable; } for (i = 0; i < flash_node->num_regulators; i++) { rc = regulator_enable(flash_node->reg_data[i].regs); if (rc) { dev_err(&led->spmi_dev->dev, "regulator enable failed\n"); goto error_regulator_enable; } } return rc; error_regulator_enable: while (i--) regulator_disable(flash_node->reg_data[i].regs); return rc; } static void qpnp_flash_led_work(struct work_struct *work) { struct flash_node_data *flash_node = container_of(work, Loading @@ -1020,27 +1150,14 @@ static void qpnp_flash_led_work(struct work_struct *work) if (!brightness) goto turn_off; if (flash_node->boost_regulator && !flash_node->flash_on) { if (regulator_count_voltages(flash_node->boost_regulator) > 0) { rc = regulator_set_voltage(flash_node->boost_regulator, flash_node->boost_voltage_max, flash_node->boost_voltage_max); if (!flash_node->flash_on && flash_node->num_regulators > 0) { rc = flash_regulator_enable(led, flash_node, true); if (rc) { dev_err(&led->spmi_dev->dev, "boost regulator set voltage failed\n"); mutex_unlock(&led->flash_led_lock); return; } } rc = regulator_enable(flash_node->boost_regulator); if (rc) { dev_err(&led->spmi_dev->dev, "Boost regulator enablement failed\n"); goto error_regulator_enable; } } if (!led->gpio_enabled && led->pinctrl) { rc = pinctrl_select_state(led->pinctrl, led->gpio_state_active); Loading Loading @@ -1523,13 +1640,8 @@ exit_flash_led_work: goto exit_flash_led_work; } error_enable_gpio: if (flash_node->boost_regulator && flash_node->flash_on) { regulator_disable(flash_node->boost_regulator); error_regulator_enable: if (regulator_count_voltages(flash_node->boost_regulator) > 0) regulator_set_voltage(flash_node->boost_regulator, 0, flash_node->boost_voltage_max); } if (flash_node->flash_on && flash_node->num_regulators > 0) flash_regulator_enable(led, flash_node, false); flash_node->flash_on = false; mutex_unlock(&led->flash_led_lock); Loading Loading @@ -1821,34 +1933,13 @@ static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led) return 0; } /* * Boost regulator probes later than flash. * Delay 2s to make sure it has been registered. */ static void qpnp_flash_led_delayed_reg_work(struct work_struct *work) { struct flash_node_data *flash_node = container_of(work, struct flash_node_data, dwork.work); int rc; flash_node->boost_regulator = regulator_get(flash_node->cdev.dev, "boost"); if (IS_ERR(flash_node->boost_regulator)) { rc = PTR_ERR(flash_node->boost_regulator); flash_node->boost_regulator = NULL; pr_err("boost regulator get failed\n"); return; } return; } static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led, struct flash_node_data *flash_node) { const char *temp_string; struct device_node *node = flash_node->cdev.dev->of_node; int rc = 0; struct device_node *temp = NULL; int rc = 0, num_regs = 0; u32 val; rc = of_property_read_string(node, "label", &temp_string); Loading Loading @@ -1914,31 +2005,14 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led, dev_err(&led->spmi_dev->dev, "Invalid peripheral type\n"); } if (of_find_property(node, "boost-supply", NULL)) { INIT_DELAYED_WORK(&flash_node->dwork, qpnp_flash_led_delayed_reg_work); flash_node->boost_regulator = regulator_get(flash_node->cdev.dev, "boost"); if (!flash_node->boost_regulator || IS_ERR(flash_node->boost_regulator)) schedule_delayed_work(&flash_node->dwork, FLASH_BOOST_REGULATOR_PROBE_DELAY_MS); rc = of_property_read_u32(node, "boost-voltage-max", &val); if (!rc) flash_node->boost_voltage_max = val; else { dev_err(&led->spmi_dev->dev, "Unable to read maximum boost regulator voltage\n"); goto error_regulator_config; } while ((temp = of_get_next_child(node, temp))) { if (of_find_property(temp, "regulator-name", NULL)) num_regs++; } return rc; if (num_regs) flash_node->num_regulators = num_regs; error_regulator_config: regulator_put(flash_node->boost_regulator); return rc; } Loading Loading @@ -2351,6 +2425,24 @@ static int qpnp_flash_led_probe(struct spmi_device *spmi) goto error_led_register; } if (&led->flash_node[i].num_regulators) { rc = flash_regulator_parse_dt(led, &led->flash_node[i]); if (rc) { dev_err(&led->spmi_dev->dev, "Unable to parse regulator data\n"); goto error_led_register; } rc = flash_regulator_setup(led, &led->flash_node[i], true); if (rc) { dev_err(&led->spmi_dev->dev, "Unable to set up regulator\n"); goto error_led_register; } } for (j = 0; j < ARRAY_SIZE(qpnp_flash_led_attrs); j++) { rc = sysfs_create_file(&led->flash_node[i].cdev.dev->kobj, Loading @@ -2370,7 +2462,7 @@ static int qpnp_flash_led_probe(struct spmi_device *spmi) (long)root); if (PTR_ERR(root) == -ENODEV) pr_err("debugfs is not enabled in kernel"); goto error_led_register; goto error_led_debugfs; } led->dbgfs_root = root; Loading @@ -2378,27 +2470,30 @@ static int qpnp_flash_led_probe(struct spmi_device *spmi) led, &flash_led_dfs_dbg_feature_fops); if (!file) { pr_err("error creating 'enable_debug' entry\n"); goto error_led_register; goto error_led_debugfs; } file = debugfs_create_file("latched", S_IRUSR | S_IWUSR, root, led, &flash_led_dfs_latched_reg_fops); if (!file) { pr_err("error creating 'latched' entry\n"); goto error_led_register; goto error_led_debugfs; } file = debugfs_create_file("strobe", S_IRUSR | S_IWUSR, root, led, &flash_led_dfs_strobe_reg_fops); if (!file) { pr_err("error creating 'strobe' entry\n"); goto error_led_register; goto error_led_debugfs; } dev_set_drvdata(&spmi->dev, led); return 0; error_led_debugfs: i = led->num_leds - 1; j = ARRAY_SIZE(qpnp_flash_led_attrs) - 1; error_led_register: for (; i >= 0; i--) { for (; j >= 0; j--) Loading @@ -2420,8 +2515,13 @@ static int qpnp_flash_led_remove(struct spmi_device *spmi) int i, j; for (i = led->num_leds - 1; i >= 0; i--) { if (led->flash_node[i].boost_regulator) regulator_put(led->flash_node[i].boost_regulator); if (led->flash_node[i].reg_data) { if (led->flash_node[i].flash_on) flash_regulator_enable(led, &led->flash_node[i], false); flash_regulator_setup(led, &led->flash_node[i], false); } for (j = 0; j < ARRAY_SIZE(qpnp_flash_led_attrs); j++) sysfs_remove_file(&led->flash_node[i].cdev.dev->kobj, &qpnp_flash_led_attrs[j].attr); Loading Loading
Documentation/devicetree/bindings/leds/leds-qpnp-flash.txt +19 −6 Original line number Diff line number Diff line Loading @@ -90,13 +90,18 @@ operational simplification. For backward compatibility purpose, switch node can Optional properties inside child node: - qcom,current : default current intensity for LED. Accepted values should be integer from 0 t 1000 inclusive, indicating 0 to 1000 mA. - boost-supply : flash LED boost power source for flash LED - boost-voltage-max : maximum voltage for flash LED boost regulator in uV. This attribute is required if boost-supply is defined. - qcom,duration : Duration for flash LED. When duration time expires, hardware will turn off flash LED. Values should be from 10 ms to 1280 ms with 10 ms incremental step. Not applicable to torch. It is required for LED:SWITCH node to handle LED used as flash. - reg<n> : reg<n> (<n> represents number. eg 0,1,2,..) property is to add support for multiple power sources. It includes two properties regulator-name and max-voltage. Required property inside regulator node: - regulator-name : This denotes this node is a regulator node and which regulator to use. Optional property inside regulator node: - max-voltage : This specifies max voltage of regulator. Some switch or boost regulator does not need this property. Example: qcom,leds@d300 { Loading Loading @@ -145,7 +150,12 @@ Example: qcom,max-current = <200>; qcom,id = <0>; qcom,current = <120>; boost-voltage-max = <3600000>; qcom,max-current = <200>; reg0 { regulator-name = "pm8226_chg_boost"; max-voltage = <3600000>; }; }; pm8226_switch: qcom,switch { Loading @@ -157,8 +167,11 @@ Example: qcom,current = <625>; qcom,duration = <1280>; qcom,max-current = <1000>; boost-supply = <pm8226_chg_boost>; boost-voltage-max = <3600000>; reg0 { regulator-name = "pm8226_chg_boost"; max-voltage = <3600000>; }; }; };
drivers/leds/leds-qpnp-flash.c +178 −78 Original line number Diff line number Diff line Loading @@ -163,16 +163,20 @@ enum current_ramp_steps { RAMP_STEP_27US, }; struct flash_regulator_data { struct regulator *regs; const char *reg_name; u32 max_volt_uv; }; /* * Configurations for each individual LED */ struct flash_node_data { struct spmi_device *spmi_dev; struct led_classdev cdev; struct regulator *boost_regulator; struct work_struct work; struct delayed_work dwork; u32 boost_voltage_max; struct flash_regulator_data *reg_data; u16 max_current; u16 prgm_current; u16 prgm_current2; Loading @@ -181,6 +185,7 @@ struct flash_node_data { u8 type; u8 trigger; u8 enable; u8 num_regulators; bool flash_on; }; Loading Loading @@ -1002,6 +1007,131 @@ led_brightness qpnp_flash_led_brightness_get(struct led_classdev *led_cdev) return led_cdev->brightness; } static int flash_regulator_parse_dt(struct qpnp_flash_led *led, struct flash_node_data *flash_node) { int i = 0, rc; struct device_node *node = flash_node->cdev.dev->of_node; struct device_node *temp = NULL; const char *temp_string; u32 val; flash_node->reg_data = devm_kzalloc(&led->spmi_dev->dev, sizeof(struct flash_regulator_data *) * flash_node->num_regulators, GFP_KERNEL); if (!flash_node->reg_data) { dev_err(&led->spmi_dev->dev, "Unable to allocate memory\n"); return -ENOMEM; } for_each_child_of_node(node, temp) { rc = of_property_read_string(temp, "regulator-name", &temp_string); if (!rc) flash_node->reg_data[i].reg_name = temp_string; else { dev_err(&led->spmi_dev->dev, "Unable to read regulator name\n"); return rc; } if (of_find_property(temp, "max-voltage", NULL)) { rc = of_property_read_u32(temp, "max-voltage", &val); if (!rc) { flash_node->reg_data[i].max_volt_uv = val; } else { dev_err(&led->spmi_dev->dev, "Unable to read max voltage\n"); return rc; } } i++; } return rc; } static int flash_regulator_setup(struct qpnp_flash_led *led, struct flash_node_data *flash_node, bool on) { int i, rc = 0; if (on == false) { i = flash_node->num_regulators; goto error_regulator_setup; } for (i = 0; i < flash_node->num_regulators; i++) { flash_node->reg_data[i].regs = regulator_get(flash_node->cdev.dev, flash_node->reg_data[i].reg_name); if (IS_ERR(flash_node->reg_data[i].regs)) { rc = PTR_ERR(flash_node->reg_data[i].regs); dev_err(&led->spmi_dev->dev, "Failed to get regulator\n"); goto error_regulator_setup; } if (regulator_count_voltages(flash_node->reg_data[i].regs) > 0) { rc = regulator_set_voltage(flash_node->reg_data[i].regs, flash_node->reg_data[i].max_volt_uv, flash_node->reg_data[i].max_volt_uv); if (rc) { dev_err(&led->spmi_dev->dev, "regulator set voltage failed\n"); regulator_put(flash_node->reg_data[i].regs); goto error_regulator_setup; } } } return rc; error_regulator_setup: while (i--) { if (regulator_count_voltages(flash_node->reg_data[i].regs) > 0) { regulator_set_voltage(flash_node->reg_data[i].regs, 0, flash_node->reg_data[i].max_volt_uv); } regulator_put(flash_node->reg_data[i].regs); } return rc; } static int flash_regulator_enable(struct qpnp_flash_led *led, struct flash_node_data *flash_node, bool on) { int i, rc = 0; if (on == false) { i = flash_node->num_regulators; goto error_regulator_enable; } for (i = 0; i < flash_node->num_regulators; i++) { rc = regulator_enable(flash_node->reg_data[i].regs); if (rc) { dev_err(&led->spmi_dev->dev, "regulator enable failed\n"); goto error_regulator_enable; } } return rc; error_regulator_enable: while (i--) regulator_disable(flash_node->reg_data[i].regs); return rc; } static void qpnp_flash_led_work(struct work_struct *work) { struct flash_node_data *flash_node = container_of(work, Loading @@ -1020,27 +1150,14 @@ static void qpnp_flash_led_work(struct work_struct *work) if (!brightness) goto turn_off; if (flash_node->boost_regulator && !flash_node->flash_on) { if (regulator_count_voltages(flash_node->boost_regulator) > 0) { rc = regulator_set_voltage(flash_node->boost_regulator, flash_node->boost_voltage_max, flash_node->boost_voltage_max); if (!flash_node->flash_on && flash_node->num_regulators > 0) { rc = flash_regulator_enable(led, flash_node, true); if (rc) { dev_err(&led->spmi_dev->dev, "boost regulator set voltage failed\n"); mutex_unlock(&led->flash_led_lock); return; } } rc = regulator_enable(flash_node->boost_regulator); if (rc) { dev_err(&led->spmi_dev->dev, "Boost regulator enablement failed\n"); goto error_regulator_enable; } } if (!led->gpio_enabled && led->pinctrl) { rc = pinctrl_select_state(led->pinctrl, led->gpio_state_active); Loading Loading @@ -1523,13 +1640,8 @@ exit_flash_led_work: goto exit_flash_led_work; } error_enable_gpio: if (flash_node->boost_regulator && flash_node->flash_on) { regulator_disable(flash_node->boost_regulator); error_regulator_enable: if (regulator_count_voltages(flash_node->boost_regulator) > 0) regulator_set_voltage(flash_node->boost_regulator, 0, flash_node->boost_voltage_max); } if (flash_node->flash_on && flash_node->num_regulators > 0) flash_regulator_enable(led, flash_node, false); flash_node->flash_on = false; mutex_unlock(&led->flash_led_lock); Loading Loading @@ -1821,34 +1933,13 @@ static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led) return 0; } /* * Boost regulator probes later than flash. * Delay 2s to make sure it has been registered. */ static void qpnp_flash_led_delayed_reg_work(struct work_struct *work) { struct flash_node_data *flash_node = container_of(work, struct flash_node_data, dwork.work); int rc; flash_node->boost_regulator = regulator_get(flash_node->cdev.dev, "boost"); if (IS_ERR(flash_node->boost_regulator)) { rc = PTR_ERR(flash_node->boost_regulator); flash_node->boost_regulator = NULL; pr_err("boost regulator get failed\n"); return; } return; } static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led, struct flash_node_data *flash_node) { const char *temp_string; struct device_node *node = flash_node->cdev.dev->of_node; int rc = 0; struct device_node *temp = NULL; int rc = 0, num_regs = 0; u32 val; rc = of_property_read_string(node, "label", &temp_string); Loading Loading @@ -1914,31 +2005,14 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led, dev_err(&led->spmi_dev->dev, "Invalid peripheral type\n"); } if (of_find_property(node, "boost-supply", NULL)) { INIT_DELAYED_WORK(&flash_node->dwork, qpnp_flash_led_delayed_reg_work); flash_node->boost_regulator = regulator_get(flash_node->cdev.dev, "boost"); if (!flash_node->boost_regulator || IS_ERR(flash_node->boost_regulator)) schedule_delayed_work(&flash_node->dwork, FLASH_BOOST_REGULATOR_PROBE_DELAY_MS); rc = of_property_read_u32(node, "boost-voltage-max", &val); if (!rc) flash_node->boost_voltage_max = val; else { dev_err(&led->spmi_dev->dev, "Unable to read maximum boost regulator voltage\n"); goto error_regulator_config; } while ((temp = of_get_next_child(node, temp))) { if (of_find_property(temp, "regulator-name", NULL)) num_regs++; } return rc; if (num_regs) flash_node->num_regulators = num_regs; error_regulator_config: regulator_put(flash_node->boost_regulator); return rc; } Loading Loading @@ -2351,6 +2425,24 @@ static int qpnp_flash_led_probe(struct spmi_device *spmi) goto error_led_register; } if (&led->flash_node[i].num_regulators) { rc = flash_regulator_parse_dt(led, &led->flash_node[i]); if (rc) { dev_err(&led->spmi_dev->dev, "Unable to parse regulator data\n"); goto error_led_register; } rc = flash_regulator_setup(led, &led->flash_node[i], true); if (rc) { dev_err(&led->spmi_dev->dev, "Unable to set up regulator\n"); goto error_led_register; } } for (j = 0; j < ARRAY_SIZE(qpnp_flash_led_attrs); j++) { rc = sysfs_create_file(&led->flash_node[i].cdev.dev->kobj, Loading @@ -2370,7 +2462,7 @@ static int qpnp_flash_led_probe(struct spmi_device *spmi) (long)root); if (PTR_ERR(root) == -ENODEV) pr_err("debugfs is not enabled in kernel"); goto error_led_register; goto error_led_debugfs; } led->dbgfs_root = root; Loading @@ -2378,27 +2470,30 @@ static int qpnp_flash_led_probe(struct spmi_device *spmi) led, &flash_led_dfs_dbg_feature_fops); if (!file) { pr_err("error creating 'enable_debug' entry\n"); goto error_led_register; goto error_led_debugfs; } file = debugfs_create_file("latched", S_IRUSR | S_IWUSR, root, led, &flash_led_dfs_latched_reg_fops); if (!file) { pr_err("error creating 'latched' entry\n"); goto error_led_register; goto error_led_debugfs; } file = debugfs_create_file("strobe", S_IRUSR | S_IWUSR, root, led, &flash_led_dfs_strobe_reg_fops); if (!file) { pr_err("error creating 'strobe' entry\n"); goto error_led_register; goto error_led_debugfs; } dev_set_drvdata(&spmi->dev, led); return 0; error_led_debugfs: i = led->num_leds - 1; j = ARRAY_SIZE(qpnp_flash_led_attrs) - 1; error_led_register: for (; i >= 0; i--) { for (; j >= 0; j--) Loading @@ -2420,8 +2515,13 @@ static int qpnp_flash_led_remove(struct spmi_device *spmi) int i, j; for (i = led->num_leds - 1; i >= 0; i--) { if (led->flash_node[i].boost_regulator) regulator_put(led->flash_node[i].boost_regulator); if (led->flash_node[i].reg_data) { if (led->flash_node[i].flash_on) flash_regulator_enable(led, &led->flash_node[i], false); flash_regulator_setup(led, &led->flash_node[i], false); } for (j = 0; j < ARRAY_SIZE(qpnp_flash_led_attrs); j++) sysfs_remove_file(&led->flash_node[i].cdev.dev->kobj, &qpnp_flash_led_attrs[j].attr); Loading