[lm-sensors] [PATCH 1/2] hwmon: ntc: Add DT support to NTC thermistor driver
Guenter Roeck
linux at roeck-us.net
Mon Mar 11 23:48:19 EST 2013
On Mon, Mar 11, 2013 at 05:21:44AM -0700, Guenter Roeck wrote:
> On Mon, Mar 11, 2013 at 07:39:46AM +0530, Naveen Krishna Chatradhi wrote:
> > This patch adds the DT support to NTC driver to parse the
> > platform data.
> >
> > Signed-off-by: Naveen Krishna Chatradhi <ch.naveen at samsung.com>
> > ---
> > drivers/hwmon/ntc_thermistor.c | 93 ++++++++++++++++++++++++++++++++--------
> > 1 file changed, 75 insertions(+), 18 deletions(-)
> >
> > diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
> > index d92b237..cfedbd3 100644
> > --- a/drivers/hwmon/ntc_thermistor.c
> > +++ b/drivers/hwmon/ntc_thermistor.c
> > @@ -26,6 +26,7 @@
> > #include <linux/math64.h>
> > #include <linux/platform_device.h>
> > #include <linux/err.h>
> > +#include <linux/of.h>
> >
> > #include <linux/platform_data/ntc_thermistor.h>
> >
> > @@ -37,6 +38,41 @@ struct ntc_compensation {
> > unsigned int ohm;
> > };
> >
> > +static const struct platform_device_id ntc_thermistor_id[] = {
> > + { "ncp15wb473", TYPE_NCPXXWB473 },
> > + { "ncp18wb473", TYPE_NCPXXWB473 },
> > + { "ncp21wb473", TYPE_NCPXXWB473 },
> > + { "ncp03wb473", TYPE_NCPXXWB473 },
> > + { "ncp15wl333", TYPE_NCPXXWL333 },
> > + { },
> > +};
> > +
> > +#ifdef CONFIG_OF
> > +static const struct of_device_id ntc_match[] = {
> > + { .compatible = "ntc,ncp15wb473", .data = (void *)TYPE_NCPXXWB473 },
> > + { .compatible = "ntc,ncp18wb473", .data = (void *)TYPE_NCPXXWB473 },
> > + { .compatible = "ntc,ncp21wb473", .data = (void *)TYPE_NCPXXWB473 },
> > + { .compatible = "ntc,ncp03wb473", .data = (void *)TYPE_NCPXXWB473 },
> > + { .compatible = "ntc,ncp15wl333", .data = (void *)TYPE_NCPXXWL333 },
>
> Better point to ntc_thermistor_id[TYPE_xxx]. See below.
>
> > + { },
> > +};
> > +MODULE_DEVICE_TABLE(of, ntc_match);
> > +#endif
> > +
> > +/* Get NTC type either from device tree or platform data. */
> > +static enum ntc_thermistor_type thermistor_get_type
> > + (struct platform_device *pdev)
> > +{
> > + if (pdev->dev.of_node) {
> > + const struct of_device_id *match;
> > + match = of_match_node(of_match_ptr(ntc_match),
> > + pdev->dev.of_node);
> > + return (unsigned int)match->data;
> > + }
> > +
> > + return platform_get_device_id(pdev)->driver_data;
> > +}
> > +
> > /*
> > * A compensation table should be sorted by the values of .ohm
> > * in descending order.
> > @@ -126,6 +162,27 @@ struct ntc_data {
> > char name[PLATFORM_NAME_SIZE];
> > };
> >
> > +#ifdef CONFIG_OF
>
> Please merge the two CONFIG_OF blocks into one.
>
> > +static void ntc_thermistor_parse_dt(struct ntc_thermistor_platform_data *pdata,
> > + struct device_node *np)
> > +{
> > + of_property_read_u32(np, "pullup-uV", &pdata->pullup_uV);
> > + of_property_read_u32(np, "pullup-ohm", &pdata->pullup_ohm);
> > + of_property_read_u32(np, "pulldown-ohm", &pdata->pulldown_ohm);
> > + if (of_find_property(np, "connected-positive", NULL))
> > + pdata->connect = NTC_CONNECTED_POSITIVE;
> > + else /* status change should be possible if not always on. */
> > + pdata->connect = NTC_CONNECTED_GROUND;
> > +}
Forgot to mention: You'll have to add a devicetree bindings file describing the
bindings.
> > +#else
> > +static void
> > +static void ntc_thermistor_parse_dt(struct ntc_thermistor_platform_data *pdata,
> > + struct device_node *np)
> > +{
> > + return;
>
> Unnecessary return statement.
>
> > +}
> > +#endif
> > +
> > static inline u64 div64_u64_safe(u64 dividend, u64 divisor)
> > {
> > if (divisor == 0 && dividend == 0)
> > @@ -313,9 +370,19 @@ static const struct attribute_group ntc_attr_group = {
> > static int ntc_thermistor_probe(struct platform_device *pdev)
> > {
> > struct ntc_data *data;
> > - struct ntc_thermistor_platform_data *pdata = pdev->dev.platform_data;
> > + struct device_node *np = pdev->dev.of_node;
> > + struct ntc_thermistor_platform_data *pdata = NULL;
>
> Unnecessary change. It doesn't hurt if pdata is initialized to non-NULL, and
> initializing it to NULL is unnecessary anyway since it is always assigned below.
>
> > int ret = 0;
> >
> > + if (np) {
> > + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
> > + if (!pdata)
> > + return -ENOMEM;
> > +
> > + ntc_thermistor_parse_dt(pdata, np);
>
> This compiles, but the resulting code would not work as the necessary fields
> in pdata are not all filled out. So I think it would be better to merge the code
> with the next patch, as both don't really work independently.
>
> > + } else
> > + pdata = pdev->dev.platform_data;
>
> Not necessary if you keep above pre-initialization.
>
> A better idea would be to move the devm_kzalloc into ntc_thermistor_parse_dt
> and return a pointer to pdata from it. Then you would have
>
> pdata = ntc_thermistor_parse_dt(np);
> if (!pdata)
> pdata = pdev->dev.platform_data;
>
> The check for np == NULL could then also be in ntc_thermistor_parse_dt and only
> be executed if CONFIG_OF is defined. This would make the code flow look much nicer.
>
> > +
> > if (!pdata) {
> > dev_err(&pdev->dev, "No platform init data supplied.\n");
> > return -ENODEV;
> > @@ -353,9 +420,9 @@ static int ntc_thermistor_probe(struct platform_device *pdev)
> > data->dev = &pdev->dev;
> > data->pdev = pdev;
> > data->pdata = pdata;
> > - strlcpy(data->name, pdev->id_entry->name, sizeof(data->name));
> > + strncpy(data->name, dev_name(&pdev->dev), PLATFORM_NAME_SIZE);
> >
> strlcpy is used to ensure 0 termination.
> sizeof(data->name) is used to ensure object size.
>
> You should introduce a variable such as pdev_id and either assign pdev->id_entry
> or the result of the of function call to it. Other code does that for example
> with
> const struct of_device_id *of_id =
> of_match_device(of_match_ptr(coda_dt_ids),
> &pdev->dev);
> const struct platform_device_id *pdev_id;
> ...
> pdev_id = of_id ? of_id->data : platform_get_device_id(pdev);
>
> and then just use pdev_id. Then you can use
> strncpy(data->name, pdev_id->name, sizeof(data->name));
>
> That requires to change .data in the of_device_id table to point to the
> platform_device_id.
>
> > - switch (pdev->id_entry->driver_data) {
> > + switch (thermistor_get_type(pdev)) {
>
> And then:
> switch (pdev_id) {
>
> > case TYPE_NCPXXWB473:
> > data->comp = ncpXXwb473;
> > data->n_comp = ARRAY_SIZE(ncpXXwb473);
> > @@ -365,9 +432,8 @@ static int ntc_thermistor_probe(struct platform_device *pdev)
> > data->n_comp = ARRAY_SIZE(ncpXXwl333);
> > break;
> > default:
> > - dev_err(&pdev->dev, "Unknown device type: %lu(%s)\n",
> > - pdev->id_entry->driver_data,
> > - pdev->id_entry->name);
> > + dev_err(&pdev->dev, "Unknown device type: %u\n",
> > + thermistor_get_type(pdev));
>
> dev_err(&pdev->dev, "Unknown device type: %lu(%s)\n",
> pdev_id->driver_data,
> pdev_id->name);
>
> > return -EINVAL;
> > }
> >
> > @@ -386,9 +452,8 @@ static int ntc_thermistor_probe(struct platform_device *pdev)
> > goto err_after_sysfs;
> > }
> >
> > - dev_info(&pdev->dev, "Thermistor %s:%d (type: %s/%lu) successfully probed.\n",
> > - pdev->name, pdev->id, pdev->id_entry->name,
> > - pdev->id_entry->driver_data);
> > + dev_info(&pdev->dev, "Thermistor successfully probed.\n");
>
> Same here again.
> dev_info(&pdev->dev, "Thermistor %s:%d (type: %s/%lu) successfully probed.\n",
> pdev->name, pdev->id, pdev_id->name,
> pdev_id->driver_data);
>
> Though I would change that to
> dev_info(&pdev->dev, "Thermistor type %s successfully probed.\n",
> pdev_id->name);
>
> since the rest of the output is either redundant (name/id) or internal
> (pdev_id->driver_data).
>
> > +
> > return 0;
> > err_after_sysfs:
> > sysfs_remove_group(&data->dev->kobj, &ntc_attr_group);
> > @@ -406,19 +471,11 @@ static int ntc_thermistor_remove(struct platform_device *pdev)
> > return 0;
> > }
> >
> > -static const struct platform_device_id ntc_thermistor_id[] = {
> > - { "ncp15wb473", TYPE_NCPXXWB473 },
> > - { "ncp18wb473", TYPE_NCPXXWB473 },
> > - { "ncp21wb473", TYPE_NCPXXWB473 },
> > - { "ncp03wb473", TYPE_NCPXXWB473 },
> > - { "ncp15wl333", TYPE_NCPXXWL333 },
> > - { },
> > -};
> > -
> > static struct platform_driver ntc_thermistor_driver = {
> > .driver = {
> > .name = "ntc-thermistor",
> > .owner = THIS_MODULE,
> > + .of_match_table = of_match_ptr(ntc_match),
> > },
> > .probe = ntc_thermistor_probe,
> > .remove = ntc_thermistor_remove,
> > --
> > 1.7.9.5
> >
> >
>
> _______________________________________________
> lm-sensors mailing list
> lm-sensors at lm-sensors.org
> http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
>
More information about the devicetree-discuss
mailing list