leds:lp55xx: use the private data instead of updating I2C device platform data
authorMilo Kim <milo.kim@ti.com>
Mon, 24 Aug 2015 07:09:55 +0000 (16:09 +0900)
committerJacek Anaszewski <j.anaszewski@samsung.com>
Fri, 28 Aug 2015 12:06:28 +0000 (14:06 +0200)
Currently, lp55xx_of_populate_pdata() allocates lp55xx_platform_data if
it's null. And it parses the DT and copies values into the
'client->dev.platform_data'. This may have architectural issue.
Platform data is configurable through the DT or I2C board info inside the
platform area. However, lp55xx common driver changes this configuration
when it is loaded. So 'client->dev.platform_data' is not null anymore.
Eventually, the driver initialization is not identical when it's unloaded
and loaded again.
The lp55xx common driver should use the private data, 'lp55xx_chip->pdata'
instead of changing the original platform data.

So, lp55xx_of_populate_pdata() is modified as follows.
* Do not update 'dev->platform_data'. Return the pointer of new allocated
   lp55xx_platform_data. Then the driver points it to private data,
   'lp55xx_chip->pdata'.
* Each lp55xx driver checks the pointer and handles an error case.

Then, original platform data configuration will be kept regardless of
loading or unloading the driver.
The driver allocates the memory and copies them from the DT if it's NULL.
After the driver is loaded again, 'client->dev.platform_data' is same as
initial load, so the driver is initialized identically.

Cc: Toshi Kikuchi <toshik@chromium.org>
Cc: linux-leds@vger.kernel.org
Signed-off-by: Milo Kim <milo.kim@ti.com>
Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
drivers/leds/leds-lp5521.c
drivers/leds/leds-lp5523.c
drivers/leds/leds-lp5562.c
drivers/leds/leds-lp55xx-common.c
drivers/leds/leds-lp55xx-common.h
drivers/leds/leds-lp8501.c

index 8ca197af2864841391edb94aaee13c85c60854ea..63a92542c8cb0953d17d5dcd8502075348dad9cf 100644 (file)
@@ -514,20 +514,19 @@ static int lp5521_probe(struct i2c_client *client,
        int ret;
        struct lp55xx_chip *chip;
        struct lp55xx_led *led;
-       struct lp55xx_platform_data *pdata;
+       struct lp55xx_platform_data *pdata = dev_get_platdata(&client->dev);
        struct device_node *np = client->dev.of_node;
 
-       if (!dev_get_platdata(&client->dev)) {
+       if (!pdata) {
                if (np) {
-                       ret = lp55xx_of_populate_pdata(&client->dev, np);
-                       if (ret < 0)
-                               return ret;
+                       pdata = lp55xx_of_populate_pdata(&client->dev, np);
+                       if (IS_ERR(pdata))
+                               return PTR_ERR(pdata);
                } else {
                        dev_err(&client->dev, "no platform data\n");
                        return -EINVAL;
                }
        }
-       pdata = dev_get_platdata(&client->dev);
 
        chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
        if (!chip)
index 584dbbcec65955d49f8e9603e129b1c0f83c2122..1d0187f42941aadfd91eb7b17d36b876484fff51 100644 (file)
@@ -880,20 +880,19 @@ static int lp5523_probe(struct i2c_client *client,
        int ret;
        struct lp55xx_chip *chip;
        struct lp55xx_led *led;
-       struct lp55xx_platform_data *pdata;
+       struct lp55xx_platform_data *pdata = dev_get_platdata(&client->dev);
        struct device_node *np = client->dev.of_node;
 
-       if (!dev_get_platdata(&client->dev)) {
+       if (!pdata) {
                if (np) {
-                       ret = lp55xx_of_populate_pdata(&client->dev, np);
-                       if (ret < 0)
-                               return ret;
+                       pdata = lp55xx_of_populate_pdata(&client->dev, np);
+                       if (IS_ERR(pdata))
+                               return PTR_ERR(pdata);
                } else {
                        dev_err(&client->dev, "no platform data\n");
                        return -EINVAL;
                }
        }
-       pdata = dev_get_platdata(&client->dev);
 
        chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
        if (!chip)
index ca85724ab138b30997f3afc643dbeb6fe590d37b..0360c59dbdc91b122d0d08273c48203e6755ca6b 100644 (file)
@@ -515,20 +515,19 @@ static int lp5562_probe(struct i2c_client *client,
        int ret;
        struct lp55xx_chip *chip;
        struct lp55xx_led *led;
-       struct lp55xx_platform_data *pdata;
+       struct lp55xx_platform_data *pdata = dev_get_platdata(&client->dev);
        struct device_node *np = client->dev.of_node;
 
-       if (!dev_get_platdata(&client->dev)) {
+       if (!pdata) {
                if (np) {
-                       ret = lp55xx_of_populate_pdata(&client->dev, np);
-                       if (ret < 0)
-                               return ret;
+                       pdata = lp55xx_of_populate_pdata(&client->dev, np);
+                       if (IS_ERR(pdata))
+                               return PTR_ERR(pdata);
                } else {
                        dev_err(&client->dev, "no platform data\n");
                        return -EINVAL;
                }
        }
-       pdata = dev_get_platdata(&client->dev);
 
        chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
        if (!chip)
index 96d51e9879c905d2c4eb6bac2325af174665a9f1..59b76833f0d32d1d114421ed17b160fd60d2a9c2 100644 (file)
@@ -543,7 +543,8 @@ void lp55xx_unregister_sysfs(struct lp55xx_chip *chip)
 }
 EXPORT_SYMBOL_GPL(lp55xx_unregister_sysfs);
 
-int lp55xx_of_populate_pdata(struct device *dev, struct device_node *np)
+struct lp55xx_platform_data *lp55xx_of_populate_pdata(struct device *dev,
+                                                     struct device_node *np)
 {
        struct device_node *child;
        struct lp55xx_platform_data *pdata;
@@ -553,17 +554,17 @@ int lp55xx_of_populate_pdata(struct device *dev, struct device_node *np)
 
        pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
        if (!pdata)
-               return -ENOMEM;
+               return ERR_PTR(-ENOMEM);
 
        num_channels = of_get_child_count(np);
        if (num_channels == 0) {
                dev_err(dev, "no LED channels\n");
-               return -EINVAL;
+               return ERR_PTR(-EINVAL);
        }
 
        cfg = devm_kzalloc(dev, sizeof(*cfg) * num_channels, GFP_KERNEL);
        if (!cfg)
-               return -ENOMEM;
+               return ERR_PTR(-ENOMEM);
 
        pdata->led_config = &cfg[0];
        pdata->num_channels = num_channels;
@@ -588,9 +589,7 @@ int lp55xx_of_populate_pdata(struct device *dev, struct device_node *np)
        /* LP8501 specific */
        of_property_read_u8(np, "pwr-sel", (u8 *)&pdata->pwr_sel);
 
-       dev->platform_data = pdata;
-
-       return 0;
+       return pdata;
 }
 EXPORT_SYMBOL_GPL(lp55xx_of_populate_pdata);
 
index cceab483edd04a14174224a0d8b253a738376e66..c7f1e6155001f6eeb76818f6a4dcf3904624c7e8 100644 (file)
@@ -202,7 +202,7 @@ extern int lp55xx_register_sysfs(struct lp55xx_chip *chip);
 extern void lp55xx_unregister_sysfs(struct lp55xx_chip *chip);
 
 /* common device tree population function */
-extern int lp55xx_of_populate_pdata(struct device *dev,
-                                   struct device_node *np);
+extern struct lp55xx_platform_data
+*lp55xx_of_populate_pdata(struct device *dev, struct device_node *np);
 
 #endif /* _LEDS_LP55XX_COMMON_H */
index d3098e395fff469c30950ce73542519f6f880c80..3f54f6f2b821d2684f326cda03ac1957ac1015ef 100644 (file)
@@ -308,20 +308,19 @@ static int lp8501_probe(struct i2c_client *client,
        int ret;
        struct lp55xx_chip *chip;
        struct lp55xx_led *led;
-       struct lp55xx_platform_data *pdata;
+       struct lp55xx_platform_data *pdata = dev_get_platdata(&client->dev);
        struct device_node *np = client->dev.of_node;
 
-       if (!dev_get_platdata(&client->dev)) {
+       if (!pdata) {
                if (np) {
-                       ret = lp55xx_of_populate_pdata(&client->dev, np);
-                       if (ret < 0)
-                               return ret;
+                       pdata = lp55xx_of_populate_pdata(&client->dev, np);
+                       if (IS_ERR(pdata))
+                               return PTR_ERR(pdata);
                } else {
                        dev_err(&client->dev, "no platform data\n");
                        return -EINVAL;
                }
        }
-       pdata = dev_get_platdata(&client->dev);
 
        chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
        if (!chip)