From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
To: Svyatoslav Ryhel <clamor95@gmail.com>
Cc: "Lee Jones" <lee@kernel.org>, "Rob Herring" <robh@kernel.org>,
"Krzysztof Kozlowski" <krzk+dt@kernel.org>,
"Conor Dooley" <conor+dt@kernel.org>,
"Jonathan Cameron" <jic23@kernel.org>,
"Lars-Peter Clausen" <lars@metafoo.de>,
"Pavel Machek" <pavel@ucw.cz>,
"Daniel Thompson" <danielt@kernel.org>,
"Jingoo Han" <jingoohan1@gmail.com>,
"Helge Deller" <deller@gmx.de>,
"Uwe Kleine-König" <u.kleine-koenig@baylibre.com>,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-iio@vger.kernel.org, linux-leds@vger.kernel.org,
dri-devel@lists.freedesktop.org, linux-fbdev@vger.kernel.org
Subject: Re: [PATCH v1 2/2] mfd: lm3533: convert to use OF
Date: Thu, 13 Feb 2025 16:57:02 +0200 [thread overview]
Message-ID: <Z64IPpW5Uhad4HjU@smile.fi.intel.com> (raw)
In-Reply-To: <20250212075845.11338-3-clamor95@gmail.com>
On Wed, Feb 12, 2025 at 09:58:42AM +0200, Svyatoslav Ryhel wrote:
> Add ability to fill pdata from device tree. Common stuff is
> filled from core driver and then pdata is filled per-device
> since all cells are optional.
...
> #include <linux/module.h>
> #include <linux/mutex.h>
> #include <linux/mfd/core.h>
> +#include <linux/of.h>
Is it used? In any case, please no OF-centric APIs in a new (feature) code.
> #include <linux/platform_device.h>
> +#include <linux/property.h>
> #include <linux/slab.h>
> #include <linux/uaccess.h>
...
> +static int lm3533_pass_of_node(struct platform_device *pdev,
pass_of_node sounds a bit awkward.
Perhaps you thought about parse_fwnode ?
> + struct lm3533_als_platform_data *pdata)
> +{
> + struct device *parent_dev = pdev->dev.parent;
> + struct device *dev = &pdev->dev;
> + struct fwnode_handle *node;
> + const char *label;
> + int val, ret;
> +
> + device_for_each_child_node(parent_dev, node) {
> + fwnode_property_read_string(node, "compatible", &label);
> +
> + if (!strcmp(label, pdev->name)) {
This is a bit strange. Why one need to compare platform device instance (!)
name with compatible which is part of ABI. This looks really wrong approach.
Needs a very good explanation on what's going on here.
Besides that the label is usually filled by LEDS core, why do we need to handle
it in a special way?
> + ret = fwnode_property_read_u32(node, "reg", &val);
> + if (ret) {
> + dev_err(dev, "reg property is missing: ret %d\n", ret);
> + return ret;
> + }
> +
> + if (val == pdev->id) {
> + dev->fwnode = node;
> + dev->of_node = to_of_node(node);
No direct access to fwnode in struct device, please use device_set_node().
> + }
> + }
> + }
> +
> + return 0;
> +}
...
> pdata = dev_get_platdata(&pdev->dev);
> if (!pdata) {
> - dev_err(&pdev->dev, "no platform data\n");
> - return -EINVAL;
> + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
> + if (!pdata)
> + return -ENOMEM;
> +
> + ret = lm3533_pass_of_node(pdev, pdata);
> + if (ret)
> + return dev_err_probe(&pdev->dev, ret,
> + "failed to get als device node\n");
With
struct device *dev = &pdev->dev;
at the top of the function will help a lot in making the code neater and easier
to read.
> + lm3533_parse_als(pdev, pdata);
> }
...
> #include <linux/leds.h>
> #include <linux/mfd/core.h>
> #include <linux/mutex.h>
> +#include <linux/of.h>
Cargo cult? "Proxy" header? Please follow IWYU principle.
> #include <linux/platform_device.h>
> +#include <linux/property.h>
> #include <linux/slab.h>
...
> +static void lm3533_parse_led(struct platform_device *pdev,
> + struct lm3533_led_platform_data *pdata)
> +{
> + struct device *dev = &pdev->dev;
> + int val, ret;
> +
> + ret = device_property_read_string(dev, "default-trigger",
> + &pdata->default_trigger);
> + if (ret)
> + pdata->default_trigger = "none";
Isn't this done already in LEDS core?
> + /* 5000 - 29800 uA (800 uA step) */
> + ret = device_property_read_u32(dev, "max-current-microamp", &val);
> + if (ret)
> + val = 5000;
> + pdata->max_current = val;
> +
> + /* 0 - 0x3f */
> + ret = device_property_read_u32(dev, "pwm", &val);
> + if (ret)
> + val = 0;
> + pdata->pwm = val;
> +}
...
> +static int lm3533_pass_of_node(struct platform_device *pdev,
> + struct lm3533_led_platform_data *pdata)
I think I already saw exactly the same piece of code. Please make sure
you have no duplications.
> +}
...
> pdata = dev_get_platdata(&pdev->dev);
> if (!pdata) {
> - dev_err(&pdev->dev, "no platform data\n");
> - return -EINVAL;
> + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
> + if (!pdata)
> + return -ENOMEM;
> +
> + ret = lm3533_pass_of_node(pdev, pdata);
> + if (ret)
> + return dev_err_probe(&pdev->dev, ret,
> + "failed to get led device node\n");
> +
> + lm3533_parse_led(pdev, pdata);
Ditto.
> }
...
> - led->cdev.name = pdata->name;
> + led->cdev.name = dev_name(&pdev->dev);
Are you sure it's a good idea?
...
> - if (!pdata->als)
> + if (!pdata->num_als)
> return 0;
>
> - lm3533_als_devs[0].platform_data = pdata->als;
> - lm3533_als_devs[0].pdata_size = sizeof(*pdata->als);
> + if (pdata->num_als > ARRAY_SIZE(lm3533_als_devs))
> + pdata->num_als = ARRAY_SIZE(lm3533_als_devs);
Looks like you want
pdata->num_als = clamp(pdata->num_als, 0, ARRAY_SIZE(lm3533_als_devs));
if (!pdata->num_als)
return 0;
instead of the above. You would need minmax.h for that.
...
> + if (pdata->leds) {
This is strange. I would expect num_leds == 0 in this case
> + for (i = 0; i < pdata->num_leds; ++i) {
> + lm3533_led_devs[i].platform_data = &pdata->leds[i];
> + lm3533_led_devs[i].pdata_size = sizeof(pdata->leds[i]);
> + }
> }
...
> +static void lm3533_parse_nodes(struct lm3533 *lm3533,
> + struct lm3533_platform_data *pdata)
> +{
> + struct fwnode_handle *node;
> + const char *label;
> +
> + device_for_each_child_node(lm3533->dev, node) {
> + fwnode_property_read_string(node, "compatible", &label);
> +
> + if (!strcmp(label, lm3533_bl_devs[pdata->num_backlights].name))
> + pdata->num_backlights++;
> +
> + if (!strcmp(label, lm3533_led_devs[pdata->num_leds].name))
> + pdata->num_leds++;
> +
> + if (!strcmp(label, lm3533_als_devs[pdata->num_als].name))
> + pdata->num_als++;
> + }
> +}
Oh, I don't like this approach. If you have compatible, you have driver_data
available, all this is not needed as it may be hard coded.
...
> if (!pdata) {
I would expect actually that legacy platform data support will be simply killed
by this patch(es). Do we have in-kernel users? If so, they can be easily
converted to use software nodes, otherwise we even don't need to care.
> - dev_err(lm3533->dev, "no platform data\n");
> - return -EINVAL;
> + pdata = devm_kzalloc(lm3533->dev, sizeof(*pdata), GFP_KERNEL);
> + if (!pdata)
> + return -ENOMEM;
> +
> + ret = device_property_read_u32(lm3533->dev,
> + "ti,boost-ovp",
> + &pdata->boost_ovp);
> + if (ret)
> + pdata->boost_ovp = LM3533_BOOST_OVP_16V;
> +
> + ret = device_property_read_u32(lm3533->dev,
> + "ti,boost-freq",
> + &pdata->boost_freq);
> + if (ret)
> + pdata->boost_freq = LM3533_BOOST_FREQ_500KHZ;
> +
> + lm3533_parse_nodes(lm3533, pdata);
> +
> + lm3533->dev->platform_data = pdata;
> }
...
> +static const struct of_device_id lm3533_match_table[] = {
> + { .compatible = "ti,lm3533" },
> + { },
No comma in the terminator entry.
> +};
...
> +static void lm3533_parse_backlight(struct platform_device *pdev,
pdev is not actually used, just pass struct device *dev directly.
Same comment to other functions in this change. It will make code more
bus independent and reusable.
> + struct lm3533_bl_platform_data *pdata)
> +{
> + struct device *dev = &pdev->dev;
> + int val, ret;
> +
> + /* 5000 - 29800 uA (800 uA step) */
> + ret = device_property_read_u32(dev, "max-current-microamp", &val);
> + if (ret)
> + val = 5000;
> + pdata->max_current = val;
> + /* 0 - 255 */
> + ret = device_property_read_u32(dev, "default-brightness", &val);
> + if (ret)
> + val = LM3533_BL_MAX_BRIGHTNESS;
> + pdata->default_brightness = val;
Isn't handled by LEDS core?
> + /* 0 - 0x3f */
> + ret = device_property_read_u32(dev, "pwm", &val);
> + if (ret)
> + val = 0;
> + pdata->pwm = val;
> +}
...
> +static int lm3533_pass_of_node(struct platform_device *pdev,
> + struct lm3533_bl_platform_data *pdata)
> +{
3rd dup?
> +}
...
> pdata = dev_get_platdata(&pdev->dev);
> if (!pdata) {
> - dev_err(&pdev->dev, "no platform data\n");
> - return -EINVAL;
> + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
> + if (!pdata)
> + return -ENOMEM;
> +
> + ret = lm3533_pass_of_node(pdev, pdata);
> + if (ret)
> + return dev_err_probe(&pdev->dev, ret,
> + "failed to get backlight device node\n");
> +
> + lm3533_parse_backlight(pdev, pdata);
> }
Ditto.
> - bd = devm_backlight_device_register(&pdev->dev, pdata->name,
> - pdev->dev.parent, bl, &lm3533_bl_ops,
> - &props);
> + bd = devm_backlight_device_register(&pdev->dev, dev_name(&pdev->dev),
I'm not sure the dev_name() is a good idea. We usually try to rely on the
predictable outcome, something like what "%pfw" prints against a certain fwnode.
> + pdev->dev.parent, bl,
> + &lm3533_bl_ops, &props);
...
Also I feel that this change may be split to a few separate logical changes.
--
With Best Regards,
Andy Shevchenko
next prev parent reply other threads:[~2025-02-13 14:57 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-02-12 7:58 [PATCH v1 0/2] mfd: lm3533: convert to use OF Svyatoslav Ryhel
2025-02-12 7:58 ` [PATCH v1 1/2] dt-bindings: mfd: Document TI LM3533 MFD Svyatoslav Ryhel
2025-02-12 19:49 ` Conor Dooley
2025-02-13 6:27 ` Svyatoslav Ryhel
2025-02-13 21:32 ` Daniel Thompson
2025-02-14 6:15 ` Svyatoslav Ryhel
2025-02-12 7:58 ` [PATCH v1 2/2] mfd: lm3533: convert to use OF Svyatoslav Ryhel
2025-02-13 14:57 ` Andy Shevchenko [this message]
2025-02-13 15:03 ` Svyatoslav Ryhel
2025-02-16 14:40 ` Jonathan Cameron
2025-02-12 11:02 ` [PATCH v1 0/2] " Andy Shevchenko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Z64IPpW5Uhad4HjU@smile.fi.intel.com \
--to=andriy.shevchenko@linux.intel.com \
--cc=clamor95@gmail.com \
--cc=conor+dt@kernel.org \
--cc=danielt@kernel.org \
--cc=deller@gmx.de \
--cc=devicetree@vger.kernel.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=jic23@kernel.org \
--cc=jingoohan1@gmail.com \
--cc=krzk+dt@kernel.org \
--cc=lars@metafoo.de \
--cc=lee@kernel.org \
--cc=linux-fbdev@vger.kernel.org \
--cc=linux-iio@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-leds@vger.kernel.org \
--cc=pavel@ucw.cz \
--cc=robh@kernel.org \
--cc=u.kleine-koenig@baylibre.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.