Loading Documentation/devicetree/bindings/leds/leds-qpnp-flash.txt +21 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,23 @@ Optional properties: when battery voltage is low - qcom,otst2-moduled-enabled : Boolean type. This enables driver to enable MASK to support OTST2 connection. - qcom,follow-otst2-rb-disabled : Boolean type. This allows driver to reset/deset module. By default, driver resets module. This entry allows driver to bypass reset module sequence. - qcom,die-current-derate-enabled: Boolean type. This enables driver to get maximum flash LED current, based on PMIC die temperature threshold to avoid significant current derate from hardware. This property is not needed if PMIC is older than PMI8994v2.0. - qcom,die-temp-vadc : VADC channel source for flash LED. This property is not needed if PMIC is older than PMI8994v2.0. - qcom,die-temp-threshold : Integer type array for PMIC die temperature threshold. Array should have at least one value. Values should be in celcius. This property is not needed if PMIC is older than PMI8994v2.0. - qcom,die-temp-derate-current : Integer type arrray for PMIC die temperature derate current. Array should have at least one value. Values should be in mA. This property is not needed if PMIC is older than PMI8994v2.0. Required properties inside child node. Chile node contains settings for each individual LED. Each LED hardware needs a node for itself and a switch node to control brightness. Loading Loading @@ -103,6 +120,10 @@ Example: qcom,vph-pwr-droop-debounce-time = <10>; qcom,headroom-sense-ch0-enabled; qcom,headroom-sense-ch1-enabled; qcom,die-current-derate-enabled; qcom,die-temp-vadc = <&pmi8994_vadc>; qcom,die-temp-threshold = <85 80 75 70 65>; qcom,die-temp-derate-current = <400 800 1200 1600 2000>; pm8226_flash0: qcom,flash_0 { label = "flash"; Loading drivers/leds/leds-qpnp-flash.c +214 −36 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include <linux/regulator/consumer.h> #include <linux/workqueue.h> #include <linux/power_supply.h> #include <linux/qpnp/qpnp-adc.h> #include "leds.h" #include <linux/debugfs.h> #include <linux/uaccess.h> Loading Loading @@ -186,6 +187,10 @@ struct flash_node_data { * Flash LED configuration read from device tree */ struct flash_led_platform_data { unsigned int temp_threshold_num; unsigned int temp_derate_curr_num; unsigned int *die_temp_derate_curr_ma; unsigned int *die_temp_threshold_degc; u16 ramp_up_step; u16 ramp_dn_step; u16 vph_pwr_droop_threshold; Loading @@ -205,6 +210,7 @@ struct flash_led_platform_data { bool power_detect_en; bool mask3_en; bool follow_rb_disable; bool die_current_derate_en; }; struct qpnp_flash_led_buffer { Loading @@ -226,6 +232,7 @@ struct qpnp_flash_led { struct flash_node_data *flash_node; struct power_supply *battery_psy; struct workqueue_struct *ordered_workq; struct qpnp_vadc_chip *vadc_dev; struct mutex flash_led_lock; struct qpnp_flash_led_buffer *log; struct dentry *dbgfs_root; Loading Loading @@ -523,19 +530,58 @@ qpnp_led_masked_write(struct spmi_device *spmi_dev, u16 addr, u8 mask, u8 val) return rc; } static int qpnp_flash_led_get_allowed_die_temp_curr(struct qpnp_flash_led *led, int64_t die_temp_degc) { int die_temp_curr_ma; if (die_temp_degc >= led->pdata->die_temp_threshold_degc[0]) die_temp_curr_ma = 0; else if (die_temp_degc >= led->pdata->die_temp_threshold_degc[1]) die_temp_curr_ma = led->pdata->die_temp_derate_curr_ma[0]; else if (die_temp_degc >= led->pdata->die_temp_threshold_degc[2]) die_temp_curr_ma = led->pdata->die_temp_derate_curr_ma[1]; else if (die_temp_degc >= led->pdata->die_temp_threshold_degc[3]) die_temp_curr_ma = led->pdata->die_temp_derate_curr_ma[2]; else if (die_temp_degc >= led->pdata->die_temp_threshold_degc[4]) die_temp_curr_ma = led->pdata->die_temp_derate_curr_ma[3]; else die_temp_curr_ma = led->pdata->die_temp_derate_curr_ma[4]; return die_temp_curr_ma; } static int64_t qpnp_flash_led_get_die_temp(struct qpnp_flash_led *led) { struct qpnp_vadc_result die_temp_result; int rc; rc = qpnp_vadc_read(led->vadc_dev, SPARE2, &die_temp_result); if (rc) { pr_err("failed to read the die temp\n"); return -EINVAL; } return die_temp_result.physical; } static int qpnp_flash_led_get_max_avail_current(struct flash_node_data *flash_node, struct qpnp_flash_led *led) { union power_supply_propval prop; int max_curr_avail_ma; int64_t chg_temp_milidegc, die_temp_degc; int max_curr_avail_ma = 2000; int allowed_die_temp_curr_ma = 2000; int rc; if (led->pdata->power_detect_en) { if (!led->battery_psy) { dev_err(&led->spmi_dev->dev, "Failed to query power supply\n"); return -EINVAL; } /* * When charging is enabled, enforce this new * enabelment sequence to reduce fuel gauge Loading @@ -545,7 +591,6 @@ qpnp_flash_led_get_max_avail_current(struct flash_node_data *flash_node, rc = qpnp_led_masked_write(led->spmi_dev, FLASH_MODULE_ENABLE_CTRL(led->base), FLASH_MODULE_ENABLE, FLASH_MODULE_ENABLE); if (rc) { dev_err(&led->spmi_dev->dev, "Module enable reg write failed\n"); Loading @@ -565,10 +610,57 @@ qpnp_flash_led_get_max_avail_current(struct flash_node_data *flash_node, } max_curr_avail_ma = (prop.intval / FLASH_LED_UA_PER_MA); } /* When thermal mitigation is available, this logic * will execute, to derate current based on PMIC die * temperature. */ if (led->pdata->die_current_derate_en) { chg_temp_milidegc = qpnp_flash_led_get_die_temp(led); if (chg_temp_milidegc < 0) return -EINVAL; die_temp_degc = div_s64(chg_temp_milidegc, 1000); allowed_die_temp_curr_ma = qpnp_flash_led_get_allowed_die_temp_curr(led, die_temp_degc); if (allowed_die_temp_curr_ma < 0) return -EINVAL; } max_curr_avail_ma = (max_curr_avail_ma >= allowed_die_temp_curr_ma) ? allowed_die_temp_curr_ma : max_curr_avail_ma; return max_curr_avail_ma; } static ssize_t qpnp_flash_led_die_temp_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qpnp_flash_led *led; struct flash_node_data *flash_node; unsigned long val; struct led_classdev *led_cdev = dev_get_drvdata(dev); ssize_t ret; ret = kstrtoul(buf, 10, &val); if (ret) return ret; flash_node = container_of(led_cdev, struct flash_node_data, cdev); led = dev_get_drvdata(&flash_node->spmi_dev->dev); /*'0' for disable die_temp feature; non-zero to enable feature*/ if (val == 0) led->pdata->die_current_derate_en = false; else led->pdata->die_current_derate_en = true; return count; } static ssize_t qpnp_led_strobe_type_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) Loading Loading @@ -658,18 +750,23 @@ static ssize_t qpnp_flash_led_max_current_show(struct device *dev, struct qpnp_flash_led *led; struct flash_node_data *flash_node; struct led_classdev *led_cdev = dev_get_drvdata(dev); int max_curr_avail_ma; int max_curr_avail_ma = 0; flash_node = container_of(led_cdev, struct flash_node_data, cdev); led = dev_get_drvdata(&flash_node->spmi_dev->dev); if (led->pdata->power_detect_en) { if (led->flash_node[0].flash_on) max_curr_avail_ma += led->flash_node[0].max_current; if (led->flash_node[1].flash_on) max_curr_avail_ma += led->flash_node[1].max_current; if (led->pdata->power_detect_en || led->pdata->die_current_derate_en) { max_curr_avail_ma = qpnp_flash_led_get_max_avail_current(flash_node, led); if (max_curr_avail_ma < 0) return -EINVAL; else max_curr_avail_ma = (int)flash_node->max_current; } return snprintf(buf, PAGE_SIZE, "%u\n", max_curr_avail_ma); Loading @@ -688,6 +785,9 @@ static struct device_attribute qpnp_flash_led_attrs[] = { __ATTR(max_allowed_current, (S_IRUGO | S_IWUSR | S_IWGRP), qpnp_flash_led_max_current_show, NULL), __ATTR(enable_die_temp_current_derate, (S_IRUGO | S_IWUSR | S_IWGRP), NULL, qpnp_flash_led_die_temp_store), }; static int qpnp_flash_led_get_thermal_derate_rate(const char *rate) Loading Loading @@ -1170,7 +1270,8 @@ static void qpnp_flash_led_work(struct work_struct *work) goto exit_flash_led_work; } if (led->pdata->power_detect_en) { if (led->pdata->power_detect_en || led->pdata->die_current_derate_en) { if (led->battery_psy) { led->battery_psy->get_property(led->battery_psy, POWER_SUPPLY_PROP_STATUS, Loading @@ -1189,6 +1290,7 @@ static void qpnp_flash_led_work(struct work_struct *work) || psy_prop.intval == POWER_SUPPLY_STATUS_NOT_CHARGING) led->charging_enabled = false; } max_curr_avail_ma = qpnp_flash_led_get_max_avail_current (flash_node, led); Loading @@ -1198,7 +1300,6 @@ static void qpnp_flash_led_work(struct work_struct *work) goto exit_flash_led_work; } } } if (led->flash_node[led->num_leds - 1].id == FLASH_LED_SWITCH) { Loading Loading @@ -1966,6 +2067,83 @@ static int qpnp_flash_led_parse_common_dt( led->pdata->follow_rb_disable = of_property_read_bool(node, "qcom,follow-otst2-rb-disabled"); led->pdata->die_current_derate_en = of_property_read_bool(node, "qcom,die-current-derate-enabled"); if (led->pdata->die_current_derate_en) { led->vadc_dev = qpnp_get_vadc(&led->spmi_dev->dev, "die-temp"); if (IS_ERR(led->vadc_dev)) { pr_err("VADC channel property Missing\n"); return -EINVAL; } if (of_find_property(node, "qcom,die-temp-threshold", &led->pdata->temp_threshold_num)) { if (led->pdata->temp_threshold_num > 0) { led->pdata->die_temp_threshold_degc = devm_kzalloc(&led->spmi_dev->dev, led->pdata->temp_threshold_num, GFP_KERNEL); if (led->pdata->die_temp_threshold_degc == NULL) { dev_err(&led->spmi_dev->dev, "failed to allocate die temp array\n"); return -ENOMEM; } led->pdata->temp_threshold_num /= sizeof(unsigned int); rc = of_property_read_u32_array(node, "qcom,die-temp-threshold", led->pdata->die_temp_threshold_degc, led->pdata->temp_threshold_num); if (rc) { dev_err(&led->spmi_dev->dev, "couldn't read temp threshold rc=%d\n", rc); return rc; } } } if (of_find_property(node, "qcom,die-temp-derate-current", &led->pdata->temp_derate_curr_num)) { if (led->pdata->temp_derate_curr_num > 0) { led->pdata->die_temp_derate_curr_ma = devm_kzalloc(&led->spmi_dev->dev, led->pdata->temp_derate_curr_num, GFP_KERNEL); if (led->pdata->die_temp_derate_curr_ma == NULL) { dev_err(&led->spmi_dev->dev, "failed to allocate die derate current array\n"); return -ENOMEM; } led->pdata->temp_derate_curr_num /= sizeof(unsigned int); rc = of_property_read_u32_array(node, "qcom,die-temp-derate-current", led->pdata->die_temp_derate_curr_ma, led->pdata->temp_derate_curr_num); if (rc) { dev_err(&led->spmi_dev->dev, "couldn't read temp limits rc =%d\n", rc); return rc; } } } if (led->pdata->temp_threshold_num != led->pdata->temp_derate_curr_num) { pr_err("Both array size are not same\n"); return -EINVAL; } } led->pinctrl = devm_pinctrl_get(&led->spmi_dev->dev); if (IS_ERR_OR_NULL(led->pinctrl)) { dev_err(&led->spmi_dev->dev, Loading Loading
Documentation/devicetree/bindings/leds/leds-qpnp-flash.txt +21 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,23 @@ Optional properties: when battery voltage is low - qcom,otst2-moduled-enabled : Boolean type. This enables driver to enable MASK to support OTST2 connection. - qcom,follow-otst2-rb-disabled : Boolean type. This allows driver to reset/deset module. By default, driver resets module. This entry allows driver to bypass reset module sequence. - qcom,die-current-derate-enabled: Boolean type. This enables driver to get maximum flash LED current, based on PMIC die temperature threshold to avoid significant current derate from hardware. This property is not needed if PMIC is older than PMI8994v2.0. - qcom,die-temp-vadc : VADC channel source for flash LED. This property is not needed if PMIC is older than PMI8994v2.0. - qcom,die-temp-threshold : Integer type array for PMIC die temperature threshold. Array should have at least one value. Values should be in celcius. This property is not needed if PMIC is older than PMI8994v2.0. - qcom,die-temp-derate-current : Integer type arrray for PMIC die temperature derate current. Array should have at least one value. Values should be in mA. This property is not needed if PMIC is older than PMI8994v2.0. Required properties inside child node. Chile node contains settings for each individual LED. Each LED hardware needs a node for itself and a switch node to control brightness. Loading Loading @@ -103,6 +120,10 @@ Example: qcom,vph-pwr-droop-debounce-time = <10>; qcom,headroom-sense-ch0-enabled; qcom,headroom-sense-ch1-enabled; qcom,die-current-derate-enabled; qcom,die-temp-vadc = <&pmi8994_vadc>; qcom,die-temp-threshold = <85 80 75 70 65>; qcom,die-temp-derate-current = <400 800 1200 1600 2000>; pm8226_flash0: qcom,flash_0 { label = "flash"; Loading
drivers/leds/leds-qpnp-flash.c +214 −36 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include <linux/regulator/consumer.h> #include <linux/workqueue.h> #include <linux/power_supply.h> #include <linux/qpnp/qpnp-adc.h> #include "leds.h" #include <linux/debugfs.h> #include <linux/uaccess.h> Loading Loading @@ -186,6 +187,10 @@ struct flash_node_data { * Flash LED configuration read from device tree */ struct flash_led_platform_data { unsigned int temp_threshold_num; unsigned int temp_derate_curr_num; unsigned int *die_temp_derate_curr_ma; unsigned int *die_temp_threshold_degc; u16 ramp_up_step; u16 ramp_dn_step; u16 vph_pwr_droop_threshold; Loading @@ -205,6 +210,7 @@ struct flash_led_platform_data { bool power_detect_en; bool mask3_en; bool follow_rb_disable; bool die_current_derate_en; }; struct qpnp_flash_led_buffer { Loading @@ -226,6 +232,7 @@ struct qpnp_flash_led { struct flash_node_data *flash_node; struct power_supply *battery_psy; struct workqueue_struct *ordered_workq; struct qpnp_vadc_chip *vadc_dev; struct mutex flash_led_lock; struct qpnp_flash_led_buffer *log; struct dentry *dbgfs_root; Loading Loading @@ -523,19 +530,58 @@ qpnp_led_masked_write(struct spmi_device *spmi_dev, u16 addr, u8 mask, u8 val) return rc; } static int qpnp_flash_led_get_allowed_die_temp_curr(struct qpnp_flash_led *led, int64_t die_temp_degc) { int die_temp_curr_ma; if (die_temp_degc >= led->pdata->die_temp_threshold_degc[0]) die_temp_curr_ma = 0; else if (die_temp_degc >= led->pdata->die_temp_threshold_degc[1]) die_temp_curr_ma = led->pdata->die_temp_derate_curr_ma[0]; else if (die_temp_degc >= led->pdata->die_temp_threshold_degc[2]) die_temp_curr_ma = led->pdata->die_temp_derate_curr_ma[1]; else if (die_temp_degc >= led->pdata->die_temp_threshold_degc[3]) die_temp_curr_ma = led->pdata->die_temp_derate_curr_ma[2]; else if (die_temp_degc >= led->pdata->die_temp_threshold_degc[4]) die_temp_curr_ma = led->pdata->die_temp_derate_curr_ma[3]; else die_temp_curr_ma = led->pdata->die_temp_derate_curr_ma[4]; return die_temp_curr_ma; } static int64_t qpnp_flash_led_get_die_temp(struct qpnp_flash_led *led) { struct qpnp_vadc_result die_temp_result; int rc; rc = qpnp_vadc_read(led->vadc_dev, SPARE2, &die_temp_result); if (rc) { pr_err("failed to read the die temp\n"); return -EINVAL; } return die_temp_result.physical; } static int qpnp_flash_led_get_max_avail_current(struct flash_node_data *flash_node, struct qpnp_flash_led *led) { union power_supply_propval prop; int max_curr_avail_ma; int64_t chg_temp_milidegc, die_temp_degc; int max_curr_avail_ma = 2000; int allowed_die_temp_curr_ma = 2000; int rc; if (led->pdata->power_detect_en) { if (!led->battery_psy) { dev_err(&led->spmi_dev->dev, "Failed to query power supply\n"); return -EINVAL; } /* * When charging is enabled, enforce this new * enabelment sequence to reduce fuel gauge Loading @@ -545,7 +591,6 @@ qpnp_flash_led_get_max_avail_current(struct flash_node_data *flash_node, rc = qpnp_led_masked_write(led->spmi_dev, FLASH_MODULE_ENABLE_CTRL(led->base), FLASH_MODULE_ENABLE, FLASH_MODULE_ENABLE); if (rc) { dev_err(&led->spmi_dev->dev, "Module enable reg write failed\n"); Loading @@ -565,10 +610,57 @@ qpnp_flash_led_get_max_avail_current(struct flash_node_data *flash_node, } max_curr_avail_ma = (prop.intval / FLASH_LED_UA_PER_MA); } /* When thermal mitigation is available, this logic * will execute, to derate current based on PMIC die * temperature. */ if (led->pdata->die_current_derate_en) { chg_temp_milidegc = qpnp_flash_led_get_die_temp(led); if (chg_temp_milidegc < 0) return -EINVAL; die_temp_degc = div_s64(chg_temp_milidegc, 1000); allowed_die_temp_curr_ma = qpnp_flash_led_get_allowed_die_temp_curr(led, die_temp_degc); if (allowed_die_temp_curr_ma < 0) return -EINVAL; } max_curr_avail_ma = (max_curr_avail_ma >= allowed_die_temp_curr_ma) ? allowed_die_temp_curr_ma : max_curr_avail_ma; return max_curr_avail_ma; } static ssize_t qpnp_flash_led_die_temp_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qpnp_flash_led *led; struct flash_node_data *flash_node; unsigned long val; struct led_classdev *led_cdev = dev_get_drvdata(dev); ssize_t ret; ret = kstrtoul(buf, 10, &val); if (ret) return ret; flash_node = container_of(led_cdev, struct flash_node_data, cdev); led = dev_get_drvdata(&flash_node->spmi_dev->dev); /*'0' for disable die_temp feature; non-zero to enable feature*/ if (val == 0) led->pdata->die_current_derate_en = false; else led->pdata->die_current_derate_en = true; return count; } static ssize_t qpnp_led_strobe_type_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) Loading Loading @@ -658,18 +750,23 @@ static ssize_t qpnp_flash_led_max_current_show(struct device *dev, struct qpnp_flash_led *led; struct flash_node_data *flash_node; struct led_classdev *led_cdev = dev_get_drvdata(dev); int max_curr_avail_ma; int max_curr_avail_ma = 0; flash_node = container_of(led_cdev, struct flash_node_data, cdev); led = dev_get_drvdata(&flash_node->spmi_dev->dev); if (led->pdata->power_detect_en) { if (led->flash_node[0].flash_on) max_curr_avail_ma += led->flash_node[0].max_current; if (led->flash_node[1].flash_on) max_curr_avail_ma += led->flash_node[1].max_current; if (led->pdata->power_detect_en || led->pdata->die_current_derate_en) { max_curr_avail_ma = qpnp_flash_led_get_max_avail_current(flash_node, led); if (max_curr_avail_ma < 0) return -EINVAL; else max_curr_avail_ma = (int)flash_node->max_current; } return snprintf(buf, PAGE_SIZE, "%u\n", max_curr_avail_ma); Loading @@ -688,6 +785,9 @@ static struct device_attribute qpnp_flash_led_attrs[] = { __ATTR(max_allowed_current, (S_IRUGO | S_IWUSR | S_IWGRP), qpnp_flash_led_max_current_show, NULL), __ATTR(enable_die_temp_current_derate, (S_IRUGO | S_IWUSR | S_IWGRP), NULL, qpnp_flash_led_die_temp_store), }; static int qpnp_flash_led_get_thermal_derate_rate(const char *rate) Loading Loading @@ -1170,7 +1270,8 @@ static void qpnp_flash_led_work(struct work_struct *work) goto exit_flash_led_work; } if (led->pdata->power_detect_en) { if (led->pdata->power_detect_en || led->pdata->die_current_derate_en) { if (led->battery_psy) { led->battery_psy->get_property(led->battery_psy, POWER_SUPPLY_PROP_STATUS, Loading @@ -1189,6 +1290,7 @@ static void qpnp_flash_led_work(struct work_struct *work) || psy_prop.intval == POWER_SUPPLY_STATUS_NOT_CHARGING) led->charging_enabled = false; } max_curr_avail_ma = qpnp_flash_led_get_max_avail_current (flash_node, led); Loading @@ -1198,7 +1300,6 @@ static void qpnp_flash_led_work(struct work_struct *work) goto exit_flash_led_work; } } } if (led->flash_node[led->num_leds - 1].id == FLASH_LED_SWITCH) { Loading Loading @@ -1966,6 +2067,83 @@ static int qpnp_flash_led_parse_common_dt( led->pdata->follow_rb_disable = of_property_read_bool(node, "qcom,follow-otst2-rb-disabled"); led->pdata->die_current_derate_en = of_property_read_bool(node, "qcom,die-current-derate-enabled"); if (led->pdata->die_current_derate_en) { led->vadc_dev = qpnp_get_vadc(&led->spmi_dev->dev, "die-temp"); if (IS_ERR(led->vadc_dev)) { pr_err("VADC channel property Missing\n"); return -EINVAL; } if (of_find_property(node, "qcom,die-temp-threshold", &led->pdata->temp_threshold_num)) { if (led->pdata->temp_threshold_num > 0) { led->pdata->die_temp_threshold_degc = devm_kzalloc(&led->spmi_dev->dev, led->pdata->temp_threshold_num, GFP_KERNEL); if (led->pdata->die_temp_threshold_degc == NULL) { dev_err(&led->spmi_dev->dev, "failed to allocate die temp array\n"); return -ENOMEM; } led->pdata->temp_threshold_num /= sizeof(unsigned int); rc = of_property_read_u32_array(node, "qcom,die-temp-threshold", led->pdata->die_temp_threshold_degc, led->pdata->temp_threshold_num); if (rc) { dev_err(&led->spmi_dev->dev, "couldn't read temp threshold rc=%d\n", rc); return rc; } } } if (of_find_property(node, "qcom,die-temp-derate-current", &led->pdata->temp_derate_curr_num)) { if (led->pdata->temp_derate_curr_num > 0) { led->pdata->die_temp_derate_curr_ma = devm_kzalloc(&led->spmi_dev->dev, led->pdata->temp_derate_curr_num, GFP_KERNEL); if (led->pdata->die_temp_derate_curr_ma == NULL) { dev_err(&led->spmi_dev->dev, "failed to allocate die derate current array\n"); return -ENOMEM; } led->pdata->temp_derate_curr_num /= sizeof(unsigned int); rc = of_property_read_u32_array(node, "qcom,die-temp-derate-current", led->pdata->die_temp_derate_curr_ma, led->pdata->temp_derate_curr_num); if (rc) { dev_err(&led->spmi_dev->dev, "couldn't read temp limits rc =%d\n", rc); return rc; } } } if (led->pdata->temp_threshold_num != led->pdata->temp_derate_curr_num) { pr_err("Both array size are not same\n"); return -EINVAL; } } led->pinctrl = devm_pinctrl_get(&led->spmi_dev->dev); if (IS_ERR_OR_NULL(led->pinctrl)) { dev_err(&led->spmi_dev->dev, Loading