diff --git a/drivers/leds/leds-is31fl319x.c b/drivers/leds/leds-is31fl319x.c index 80f38dba0fba..83cb769d8cb4 100644 --- a/drivers/leds/leds-is31fl319x.c +++ b/drivers/leds/leds-is31fl319x.c @@ -98,7 +98,7 @@ struct is31fl319x_chip { struct is31fl319x_chip *chip; struct led_classdev cdev; u32 max_microamp; - bool configured; + struct fwnode_handle *fwnode; } leds[IS31FL319X_MAX_LEDS]; }; @@ -363,31 +363,17 @@ static const struct of_device_id of_is31fl319x_match[] = { }; MODULE_DEVICE_TABLE(of, of_is31fl319x_match); -static int is31fl319x_parse_child_fw(const struct device *dev, - const struct fwnode_handle *child, - struct is31fl319x_led *led, - struct is31fl319x_chip *is31) +static void is31_free_fwnode(void *data) { - struct led_classdev *cdev = &led->cdev; - int ret; + struct is31fl319x_chip *is31 = data; + int i; - if (fwnode_property_read_string(child, "label", &cdev->name)) - cdev->name = fwnode_get_name(child); + for (i = 0; i < is31->cdef->num_leds; i++) { + if (is31->leds[i].fwnode) + fwnode_handle_put(is31->leds[i].fwnode); - ret = fwnode_property_read_string(child, "linux,default-trigger", &cdev->default_trigger); - if (ret < 0 && ret != -EINVAL) /* is optional */ - return ret; - - led->max_microamp = is31->cdef->current_default; - ret = fwnode_property_read_u32(child, "led-max-microamp", &led->max_microamp); - if (!ret) { - if (led->max_microamp < is31->cdef->current_min) - return -EINVAL; /* not supported */ - led->max_microamp = min(led->max_microamp, - is31->cdef->current_max); + is31->leds[i].fwnode = NULL; } - - return 0; } static int is31fl319x_parse_fw(struct device *dev, struct is31fl319x_chip *is31) @@ -402,6 +388,12 @@ static int is31fl319x_parse_fw(struct device *dev, struct is31fl319x_chip *is31) "Failed to get shutdown gpio\n"); is31->cdef = device_get_match_data(dev); + if (!is31->cdef) + return -ENODEV; + + ret = devm_add_action_or_reset(dev, is31_free_fwnode, is31); + if (ret) + return ret; count = 0; device_for_each_child_node_scoped(dev, child) @@ -427,14 +419,20 @@ static int is31fl319x_parse_fw(struct device *dev, struct is31fl319x_chip *is31) led = &is31->leds[reg - 1]; - if (led->configured) + if (led->fwnode) return dev_err_probe(dev, -EINVAL, "led %u is already configured\n", reg); - ret = is31fl319x_parse_child_fw(dev, child, led, is31); - if (ret) - return dev_err_probe(dev, ret, "led %u DT parsing failed\n", reg); + led->max_microamp = is31->cdef->current_default; + ret = fwnode_property_read_u32(child, "led-max-microamp", &led->max_microamp); + if (!ret) { + if (led->max_microamp < is31->cdef->current_min) + return dev_err_probe(dev, -EINVAL, "invalid maximum current\n"); - led->configured = true; + led->max_microamp = min(led->max_microamp, + is31->cdef->current_max); + } + + led->fwnode = fwnode_handle_get(child); } is31->audio_gain_db = 0; @@ -531,7 +529,7 @@ static int is31fl319x_probe(struct i2c_client *client) */ aggregated_led_microamp = is31->cdef->current_max; for (i = 0; i < is31->cdef->num_leds; i++) - if (is31->leds[i].configured && + if (is31->leds[i].fwnode && is31->leds[i].max_microamp < aggregated_led_microamp) aggregated_led_microamp = is31->leds[i].max_microamp; @@ -545,14 +543,17 @@ static int is31fl319x_probe(struct i2c_client *client) for (i = 0; i < is31->cdef->num_leds; i++) { struct is31fl319x_led *led = &is31->leds[i]; + struct led_init_data init_data = {}; - if (!led->configured) + if (!led->fwnode) continue; + init_data.fwnode = led->fwnode; + led->chip = is31; led->cdev.brightness_set_blocking = is31->cdef->brightness_set; - err = devm_led_classdev_register(&client->dev, &led->cdev); + err = devm_led_classdev_register_ext(&client->dev, &led->cdev, &init_data); if (err < 0) return err; }