From: Jonathan Cameron <jic23@kernel.org>
To: Crt Mori <cmo@melexis.com>
Cc: linux-iio@vger.kernel.org
Subject: Re: [PATCH v4 2/3] iio: temperature: Adding support for MLX90632
Date: Tue, 12 Dec 2017 20:50:26 +0000 [thread overview]
Message-ID: <20171212205026.5cb3203f@archlinux> (raw)
In-Reply-To: <20171211091931.8575-1-cmo@melexis.com>
On Mon, 11 Dec 2017 10:19:31 +0100
Crt Mori <cmo@melexis.com> wrote:
> Melexis has just released Infra Red temperature sensor MLX90632 used
> for contact-less temperature measurement. Driver provides basic
> functionality for reporting object (and ambient) temperature with
> support for object emissivity.
>
> Signed-off-by: Crt Mori <cmo@melexis.com>
Out of curiosity, how are you testing runtime pm? Normally I'd expect
this driver to be deliberately putting the hardware to sleep but it
isn't doing so that I can see.
A few minor comments inline.
Jonathan
> ---
> MAINTAINERS | 7 +
> drivers/iio/temperature/Kconfig | 12 +
> drivers/iio/temperature/Makefile | 1 +
> drivers/iio/temperature/mlx90632.c | 774 +++++++++++++++++++++++++++++++++++++
> 4 files changed, 794 insertions(+)
> create mode 100644 drivers/iio/temperature/mlx90632.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 2d3d750b19c0..81aec02b08b8 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -8690,6 +8690,13 @@ W: http://www.melexis.com
> S: Supported
> F: drivers/iio/temperature/mlx90614.c
>
> +MELEXIS MLX90632 DRIVER
> +M: Crt Mori <cmo@melexis.com>
> +L: linux-iio@vger.kernel.org
> +W: http://www.melexis.com
> +S: Supported
> +F: drivers/iio/temperature/mlx90632.c
> +
> MELFAS MIP4 TOUCHSCREEN DRIVER
> M: Sangwon Jee <jeesw@melfas.com>
> W: http://www.melfas.com
> diff --git a/drivers/iio/temperature/Kconfig b/drivers/iio/temperature/Kconfig
> index 5378976d6d27..82e4a62745e2 100644
> --- a/drivers/iio/temperature/Kconfig
> +++ b/drivers/iio/temperature/Kconfig
> @@ -43,6 +43,18 @@ config MLX90614
> This driver can also be built as a module. If so, the module will
> be called mlx90614.
>
> +config MLX90632
> + tristate "MLX90632 contact-less infrared sensor with medical accuracy"
> + depends on I2C
> + select REGMAP_I2C
> + help
> + If you say yes here you get support for the Melexis
> + MLX90632 contact-less infrared sensor with medical accuracy
> + connected with I2C.
> +
> + This driver can also be built as a module. If so, the module will
> + be called mlx90632.
> +
<snip>
> +static int mlx90632_probe(struct i2c_client *client,
> + const struct i2c_device_id *id)
> +{
> + struct iio_dev *indio_dev;
> + struct mlx90632_data *mlx90632;
> + struct regmap *regmap;
> + int ret;
> + unsigned int read;
> +
> + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*mlx90632));
> + if (!indio_dev) {
> + dev_err(&client->dev, "Failed to allocate device");
> + return -ENOMEM;
> + }
> +
> + regmap = devm_regmap_init_i2c(client, &mlx90632_regmap);
> + if (IS_ERR(regmap)) {
> + ret = PTR_ERR(regmap);
> + dev_err(&client->dev, "Failed to allocate regmap: %d\n", ret);
> + return ret;
> + }
> +
> + mlx90632 = iio_priv(indio_dev);
> + i2c_set_clientdata(client, indio_dev);
> + mlx90632->client = client;
> + mlx90632->regmap = regmap;
> +
> + mutex_init(&mlx90632->lock);
> + mlx90632_wakeup(mlx90632);
> +
> + indio_dev->dev.parent = &client->dev;
> + indio_dev->name = id->name;
> + indio_dev->modes = INDIO_DIRECT_MODE;
> + indio_dev->info = &mlx90632_info;
> + indio_dev->channels = mlx90632_channels;
> + indio_dev->num_channels = ARRAY_SIZE(mlx90632_channels);
> +
> + ret = regmap_read(mlx90632->regmap, MLX90632_EE_VERSION, &read);
> + if (ret < 0) {
> + dev_err(&client->dev, "read of version failed: %d\n", ret);
> + return ret;
> + }
> + if (read == MLX90632_ID_MEDICAL) {
> + dev_dbg(&client->dev,
> + "Detected Medical EEPROM calibration %x", read);
> + } else if (read == MLX90632_ID_CONSUMER) {
> + dev_dbg(&client->dev,
> + "Detected Consumer EEPROM calibration %x", read);
> + } else {
> + dev_err(&client->dev,
> + "Chip EEPROM version mismatch %x (expected %x or %x)",
> + read, MLX90632_ID_CONSUMER, MLX90632_ID_MEDICAL);
> + return -EPROTONOSUPPORT;
> + }
> +
> + mlx90632->emissivity = 1000;
> +
> + return iio_device_register(indio_dev);
> +}
> +
> +static int mlx90632_remove(struct i2c_client *client)
> +{
> + struct iio_dev *indio_dev = i2c_get_clientdata(client);
> + struct mlx90632_data *data = iio_priv(indio_dev);
> +
> + iio_device_unregister(indio_dev);
> +
> + pm_runtime_disable(&client->dev);
> + if (!pm_runtime_status_suspended(&client->dev))
> + mlx90632_sleep(data);
> + pm_runtime_set_suspended(&client->dev);
> +
> + return 0;
> +}
> +
> +static const struct i2c_device_id mlx90632_id[] = {
> + { "mlx90632", 0 },
> + { }
> +};
> +MODULE_DEVICE_TABLE(i2c, mlx90632_id);
> +
> +static const struct of_device_id mlx90632_of_match[] = {
> + { .compatible = "melexis,mlx90632" },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, mlx90632_of_match);
> +
> +static int __maybe_unused mlx90632_pm_suspend(struct device *dev)
> +{
> + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
> + struct mlx90632_data *data = iio_priv(indio_dev);
> +
> + regcache_sync(data->regmap);
This could be syncing to a runtime sleeping device. Also not
needed as the cache should be right anyway I think.
> +
> + if (pm_runtime_active(dev))
> + return mlx90632_sleep(data);
This prevents the device from sleeping twice, but nothing
stops it from coming up in resume if it was already in runtime pm.
> +
> + return 0;
> +}
> +
> +static int __maybe_unused mlx90632_pm_resume(struct device *dev)
> +{
> + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
> + struct mlx90632_data *data = iio_priv(indio_dev);
> + int err;
> +
> + regcache_mark_dirty(data->regmap);
> + regcache_cache_only(data->regmap, false);
> + err = regcache_sync(data->regmap);
> + if (err < 0) {
> + dev_err(dev, "Failed to sync regmap registers: %d\n", err);
> + return err;
> + }
> +
> + err = mlx90632_wakeup(data);
> + if (err < 0)
> + return err;
> +
> + pm_runtime_set_active(dev);
> + pm_runtime_enable(dev);
> +
> + return 0;
> +}
> +
> +static int __maybe_unused mlx90632_pm_runtime_suspend(struct device *dev)
> +{
> + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
> + struct mlx90632_data *mlx90632 = iio_priv(indio_dev);
> +
> + regcache_sync(mlx90632->regmap);
Why sync here? The cache should be in sync already.
> +
> + return mlx90632_sleep(mlx90632);
> +}
> +
> +static int __maybe_unused mlx90632_pm_runtime_resume(struct device *dev)
> +{
> + s32 ret;
> + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
> + struct mlx90632_data *mlx90632 = iio_priv(indio_dev);
> +
> + regcache_mark_dirty(mlx90632->regmap);
Technically it doesn't matter much, but I think the convention is to
normally mark the cache dirty when it becomes possible for it to be dirty
- that is during suspend.
> + regcache_cache_only(mlx90632->regmap, false);
> + ret = regcache_sync(mlx90632->regmap);
> + if (ret < 0) {
> + dev_err(dev, "Failed to sync regmap registers: %d\n", ret);
> + return ret;
> + }
> +
> + return mlx90632_wakeup(mlx90632);
This doesn't look quite right. What if the device was in runtime suspend
before full suspend? Would expect it to return to that state on resume
but not runtime_resume.
> +}
> +
> +static const struct dev_pm_ops mlx90632_pm_ops = {
> + SET_SYSTEM_SLEEP_PM_OPS(mlx90632_pm_suspend, mlx90632_pm_resume)
> + SET_RUNTIME_PM_OPS(mlx90632_pm_runtime_suspend,
> + mlx90632_pm_runtime_resume, NULL)
> +};
> +
> +static struct i2c_driver mlx90632_driver = {
> + .driver = {
> + .name = "mlx90632",
> + .of_match_table = mlx90632_of_match,
> + .pm = &mlx90632_pm_ops,
> + },
> + .probe = mlx90632_probe,
> + .remove = mlx90632_remove,
> + .id_table = mlx90632_id,
> +};
> +module_i2c_driver(mlx90632_driver);
> +
> +MODULE_AUTHOR("Crt Mori <cmo@melexis.com>");
> +MODULE_DESCRIPTION("Melexis MLX90632 contactless Infra Red temperature sensor driver");
> +MODULE_LICENSE("GPL v2");
next prev parent reply other threads:[~2017-12-12 20:50 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-12-11 9:19 [PATCH v4 2/3] iio: temperature: Adding support for MLX90632 Crt Mori
2017-12-12 20:50 ` Jonathan Cameron [this message]
2017-12-12 21:40 ` Crt Mori
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=20171212205026.5cb3203f@archlinux \
--to=jic23@kernel.org \
--cc=cmo@melexis.com \
--cc=linux-iio@vger.kernel.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox