diff mbox series

[leds,v2,28/50] leds: is31fl319x: refactor to register LEDs while parsing DT

Message ID 20200917223338.14164-29-marek.behun@nic.cz
State New
Headers show
Series None | expand

Commit Message

Marek BehĂșn Sept. 17, 2020, 10:33 p.m. UTC
Refactor the code so that LEDs are registered while device tree is being
parsed.

Signed-off-by: Marek BehĂșn <marek.behun@nic.cz>
Cc: H. Nikolaus Schaller <hns@goldelico.com>
Cc: Grant Feng <von81@163.com>
---
 drivers/leds/leds-is31fl319x.c | 174 ++++++++++++++-------------------
 1 file changed, 76 insertions(+), 98 deletions(-)
diff mbox series

Patch

diff --git a/drivers/leds/leds-is31fl319x.c b/drivers/leds/leds-is31fl319x.c
index 8e3e02d959989..1dae319b03d60 100644
--- a/drivers/leds/leds-is31fl319x.c
+++ b/drivers/leds/leds-is31fl319x.c
@@ -209,86 +209,6 @@  static u32 is31fl319x_parse_audio_gain(struct device *dev)
 	return result;;
 }
 
-static int is31fl319x_parse_child_dt(const struct device *dev,
-				     const struct device_node *child,
-				     struct is31fl319x_led *led)
-{
-	struct led_classdev *cdev = &led->cdev;
-	int ret;
-
-	if (of_property_read_string(child, "label", &cdev->name))
-		cdev->name = child->name;
-
-	ret = of_property_read_string(child, "linux,default-trigger",
-				      &cdev->default_trigger);
-	if (ret < 0 && ret != -EINVAL) /* is optional */
-		return ret;
-
-	return 0;
-}
-
-static int is31fl319x_parse_dt(struct device *dev,
-			       struct is31fl319x_chip *is31)
-{
-	struct device_node *np = dev_of_node(dev), *child;
-	int count;
-	int ret;
-
-	if (!np)
-		return -ENODEV;
-
-	is31->cdef = device_get_match_data(dev);
-
-	count = of_get_available_child_count(np);
-
-	dev_dbg(dev, "probing with %d leds defined in DT\n", count);
-
-	if (!count || count > is31->cdef->num_leds) {
-		dev_err(dev, "Number of leds defined must be between 1 and %u\n",
-			is31->cdef->num_leds);
-		return -ENODEV;
-	}
-
-	for_each_available_child_of_node(np, child) {
-		struct is31fl319x_led *led;
-		u32 reg;
-
-		ret = of_property_read_u32(child, "reg", &reg);
-		if (ret) {
-			dev_err(dev, "Failed to read led 'reg' property\n");
-			goto put_child_node;
-		}
-
-		if (reg < 1 || reg > is31->cdef->num_leds) {
-			dev_err(dev, "invalid led reg %u\n", reg);
-			ret = -EINVAL;
-			goto put_child_node;
-		}
-
-		led = &is31->leds[reg - 1];
-
-		if (led->configured) {
-			dev_err(dev, "led %u is already configured\n", reg);
-			ret = -EINVAL;
-			goto put_child_node;
-		}
-
-		ret = is31fl319x_parse_child_dt(dev, child, led);
-		if (ret) {
-			dev_err(dev, "led %u DT parsing failed\n", reg);
-			goto put_child_node;
-		}
-
-		led->configured = true;
-	}
-
-	return 0;
-
-put_child_node:
-	of_node_put(child);
-	return ret;
-}
-
 static bool is31fl319x_readable_reg(struct device *dev, unsigned int reg)
 { /* we have no readable registers */
 	return false;
@@ -345,6 +265,78 @@  static inline int is31fl319x_db_to_gain(u32 dezibel)
 	return dezibel / IS31FL319X_AUDIO_GAIN_DB_STEP;
 }
 
+static int is31fl319x_led_register(struct device *dev,
+				   struct is31fl319x_chip *is31,
+				   struct device_node *np)
+{
+	struct is31fl319x_led *led;
+	u32 reg;
+	int ret;
+
+	ret = of_property_read_u32(np, "reg", &reg);
+	if (ret) {
+		dev_err(dev, "Cannot read reg property of %pOF\n", np);
+		return ret;
+	}
+
+	if (reg < 1 || reg > is31->cdef->num_leds) {
+		dev_err(dev, "Node %pOF has invalid reg property\n", np);
+		return -EINVAL;
+	}
+
+	led = &is31->leds[reg - 1];
+
+	if (led->configured) {
+		dev_err(dev, "Node %pOF 'reg' conflicts with another LED\n",
+			np);
+		return -EEXIST;
+	}
+
+	if (of_property_read_string(np, "label", &led->cdev.name))
+		led->cdev.name = np->name;
+
+	ret = of_property_read_string(np, "linux,default-trigger",
+				      &led->cdev.default_trigger);
+	if (ret < 0 && ret != -EINVAL) /* is optional */
+		return ret;
+
+	led->configured = true;
+	led->chip = is31;
+	led->cdev.brightness_set_blocking = is31fl319x_brightness_set;
+
+	ret = devm_led_classdev_register(dev, &led->cdev);
+	if (ret)
+		dev_err(dev, "Failed to register LED for node %pOF\n", np);
+
+	return ret;
+}
+
+static int is31fl319x_parse_and_register(struct device *dev,
+					 struct is31fl319x_chip *is31)
+{
+	struct device_node *np = dev_of_node(dev), *child;
+	int ret, count;
+
+	count = of_get_available_child_count(np);
+	if (count < 1 || count > is31->cdef->num_leds) {
+		dev_err(dev, "Between 1 and %u LEDs have to be defined\n",
+			is31->cdef->num_leds);
+		return -ENODEV;
+	}
+
+	dev_dbg(dev, "probing with %d leds defined in DT\n", count);
+
+	for_each_available_child_of_node(np, child) {
+		ret = is31fl319x_led_register(dev, is31, child);
+		if (ret) {
+			of_node_put(child);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
 static int is31fl319x_probe(struct i2c_client *client,
 			    const struct i2c_device_id *id)
 {
@@ -353,7 +345,6 @@  static int is31fl319x_probe(struct i2c_client *client,
 	struct gpio_desc *shutdown_gpio;
 	u32 audio_gain_db;
 	int err;
-	int i = 0;
 	u32 aggregated_led_microamp;
 
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
@@ -388,11 +379,8 @@  static int is31fl319x_probe(struct i2c_client *client,
 
 	mutex_init(&is31->lock);
 
-	err = is31fl319x_parse_dt(&client->dev, is31);
-	if (err)
-		goto free_mutex;
-
 	is31->client = client;
+	is31->cdef = device_get_match_data(dev);
 	is31->regmap = devm_regmap_init_i2c(client, &regmap_config);
 	if (IS_ERR(is31->regmap)) {
 		dev_err(&client->dev, "failed to allocate register map\n");
@@ -417,19 +405,9 @@  static int is31fl319x_probe(struct i2c_client *client,
 		     is31fl319x_microamp_to_cs(dev, aggregated_led_microamp) |
 		     is31fl319x_db_to_gain(audio_gain_db));
 
-	for (i = 0; i < is31->cdef->num_leds; i++) {
-		struct is31fl319x_led *led = &is31->leds[i];
-
-		if (!led->configured)
-			continue;
-
-		led->chip = is31;
-		led->cdev.brightness_set_blocking = is31fl319x_brightness_set;
-
-		err = devm_led_classdev_register(&client->dev, &led->cdev);
-		if (err < 0)
-			goto free_mutex;
-	}
+	err = is31fl319x_parse_and_register(dev, is31);
+	if (err)
+		goto free_mutex;
 
 	return 0;