From: Jonathan Cameron <jic23@kernel.org>
To: Gregor Boirie <gregor.boirie@parrot.com>, linux-iio@vger.kernel.org
Cc: Hartmut Knaack <knaack.h@gmx.de>,
Lars-Peter Clausen <lars@metafoo.de>,
Peter Meerwald <pmeerw@pmeerw.net>,
Geert Uytterhoeven <geert@linux-m68k.org>,
Irina Tirdea <irina.tirdea@intel.com>,
Cristina Moraru <cristina.moraru09@gmail.com>,
Daniel Baluta <daniel.baluta@intel.com>,
Julia Lawall <Julia.Lawall@lip6.fr>
Subject: Re: [PATCH v2 5/5] iio:magnetometer:ak8975: triggered buffer support
Date: Sat, 5 Mar 2016 15:45:41 +0000 [thread overview]
Message-ID: <56DAFF25.4080709@kernel.org> (raw)
In-Reply-To: <49f851580f1e33c8753921f66935cf92bf40c62f.1457001111.git.gregor.boirie@parrot.com>
On 03/03/16 10:44, Gregor Boirie wrote:
> This will be used together with an external trigger (e.g hrtimer based
> software trigger).
>
> Signed-off-by: Gregor Boirie <gregor.boirie@parrot.com>
A few little bits and bobs inline. Mostly stuff that I think could be
a little easier to read (at the cost of the odd extra line of code).
Jonathan
> ---
> drivers/iio/magnetometer/Kconfig | 2 +
> drivers/iio/magnetometer/ak8975.c | 150 +++++++++++++++++++++++++++++++-------
> 2 files changed, 125 insertions(+), 27 deletions(-)
>
> diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig
> index 021dc53..d9834ed 100644
> --- a/drivers/iio/magnetometer/Kconfig
> +++ b/drivers/iio/magnetometer/Kconfig
> @@ -9,6 +9,8 @@ config AK8975
> tristate "Asahi Kasei AK 3-Axis Magnetometer"
> depends on I2C
> depends on GPIOLIB || COMPILE_TEST
> + select IIO_BUFFER
> + select IIO_TRIGGERED_BUFFER
> help
> Say yes here to build support for Asahi Kasei AK8975, AK8963,
> AK09911 or AK09912 3-Axis Magnetometer.
> diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c
> index 95c68952..9559ab8 100644
> --- a/drivers/iio/magnetometer/ak8975.c
> +++ b/drivers/iio/magnetometer/ak8975.c
> @@ -36,6 +36,12 @@
>
> #include <linux/iio/iio.h>
> #include <linux/iio/sysfs.h>
> +#include <linux/iio/buffer.h>
> +#include <linux/iio/trigger.h>
> +#include <linux/iio/trigger_consumer.h>
> +#include <linux/iio/triggered_buffer.h>
> +#include <linux/regulator/consumer.h>
> +
> /*
> * Register definitions, as well as various shifts and masks to get at the
> * individual fields of the registers.
> @@ -617,22 +623,15 @@ static int wait_conversion_complete_interrupt(struct ak8975_data *data)
> return ret > 0 ? 0 : -ETIME;
> }
>
> -/*
> - * Emits the raw flux value for the x, y, or z axis.
> - */
> -static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val)
> +static int ak8975_start_read_axis(struct ak8975_data *data,
> + const struct i2c_client *client)
> {
> - struct ak8975_data *data = iio_priv(indio_dev);
> - struct i2c_client *client = data->client;
> - int ret;
> -
> - mutex_lock(&data->lock);
> -
> /* Set up the device for taking a sample. */
> - ret = ak8975_set_mode(data, MODE_ONCE);
> - if (ret < 0) {
> + int ret = ak8975_set_mode(data, MODE_ONCE);
> +
> + if (ret) {
> dev_err(&client->dev, "Error in setting operating mode\n");
> - goto exit;
> + return ret;
> }
>
> /* Wait for the conversion to complete. */
> @@ -643,7 +642,7 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val)
> else
> ret = wait_conversion_complete_polled(data);
> if (ret < 0)
> - goto exit;
> + return ret;
>
> /* This will be executed only for non-interrupt based waiting case */
> if (ret & data->def->ctrl_masks[ST1_DRDY]) {
> @@ -651,32 +650,46 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val)
> data->def->ctrl_regs[ST2]);
> if (ret < 0) {
> dev_err(&client->dev, "Error in reading ST2\n");
> - goto exit;
> + return ret;
> }
> if (ret & (data->def->ctrl_masks[ST2_DERR] |
> data->def->ctrl_masks[ST2_HOFL])) {
> dev_err(&client->dev, "ST2 status error 0x%x\n", ret);
> - ret = -EINVAL;
> - goto exit;
> + return -EINVAL;
> }
> }
>
> - /* Read the flux value from the appropriate register
> - (the register is specified in the iio device attributes). */
> - ret = i2c_smbus_read_word_data(client, data->def->data_regs[index]);
> - if (ret < 0) {
> - dev_err(&client->dev, "Read axis data fails\n");
> + return 0;
> +}
> +
> +/*
> + * Retrieve raw flux value for one of the x, y, or z axis.
Single line comment so should probably have single line comment syntax
(or I'll get a 'fix' patch for it ;)
> + */
> +static int ak8975_read_axis(struct ak8975_data *data, int index, int *val)
> +{
> + int ret;
> + const struct i2c_client *client = data->client;
> + const struct ak_def *def = data->def;
> +
> + mutex_lock(&data->lock);
> +
> + ret = ak8975_start_read_axis(data, client);
> + if (ret)
> + goto exit;
> +
> + ret = i2c_smbus_read_word_data(client, def->data_regs[index]);
> + if (ret < 0)
> goto exit;
> - }
>
> mutex_unlock(&data->lock);
>
> /* Clamp to valid range. */
> - *val = clamp_t(s16, ret, -data->def->range, data->def->range);
> + *val = clamp_t(s16, ret, -def->range, def->range);
> return IIO_VAL_INT;
>
> exit:
> mutex_unlock(&data->lock);
> + dev_err(&client->dev, "Error in reading axis\n");
> return ret;
> }
>
> @@ -689,7 +702,7 @@ static int ak8975_read_raw(struct iio_dev *indio_dev,
>
> switch (mask) {
> case IIO_CHAN_INFO_RAW:
Not sure I'd have bothered with this change...
> - return ak8975_read_axis(indio_dev, chan->address, val);
> + return ak8975_read_axis(data, chan->address, val);
> case IIO_CHAN_INFO_SCALE:
> *val = 0;
> *val2 = data->raw_to_gauss[chan->address];
> @@ -728,12 +741,25 @@ static const struct attribute_group ak8975_attrs_group = {
> .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
> BIT(IIO_CHAN_INFO_SCALE), \
> .address = index, \
> + .scan_index = index, \
> + .scan_type = { \
> + .sign = 's', \
> + .realbits = 16, \
> + .storagebits = 16, \
> + .shift = 0, \
Don't specify shift if it is 0 as that's the default.
> + .endianness = IIO_CPU \
> + } \
> }
>
> static const struct iio_chan_spec ak8975_channels[] = {
> - AK8975_CHANNEL(X, 0), AK8975_CHANNEL(Y, 1), AK8975_CHANNEL(Z, 2),
> + AK8975_CHANNEL(X, 0),
> + AK8975_CHANNEL(Y, 1),
> + AK8975_CHANNEL(Z, 2),
An unrelated change but I guess minor enough that it isn't worth it's own patch
> + IIO_CHAN_SOFT_TIMESTAMP(3),
> };
>
> +static const unsigned long ak8975_scan_masks[] = { 0x7, 0 };
> +
> static const struct iio_info ak8975_info = {
> .read_raw = &ak8975_read_raw,
> .driver_module = THIS_MODULE,
> @@ -768,6 +794,51 @@ static const char *ak8975_match_acpi_device(struct device *dev,
> return dev_name(dev);
> }
>
> +static irqreturn_t ak8975_handle_trigger(int irq, void *p)
> +{
> + struct iio_poll_func *pf = p;
> + struct iio_dev *indio_dev = pf->indio_dev;
> + struct ak8975_data *data = iio_priv(indio_dev);
> + const struct i2c_client *client = data->client;
> + const struct ak_def *def = data->def;
> + int ret;
> + s16 buff[8]; /* 3 x 16 bits axis values + 1 aligned 64 bits timestamp */
> +
> + mutex_lock(&data->lock);
> +
> + ret = ak8975_start_read_axis(data, client);
> + if (ret)
> + goto unlock;
> +
> + /*
> + * For each axis, read the flux value from the appropriate register
> + * (the register is specified in the iio device attributes).
> + */
> + ret = i2c_smbus_read_i2c_block_data_or_emulated(client,
> + def->data_regs[0],
> + 3 * sizeof(buff[0]),
> + (u8 *)buff);
> + if (ret < 0)
> + goto unlock;
> +
> + mutex_unlock(&data->lock);
> +
> + /* Clamp to valid range. */
> + buff[0] = clamp_t(s16, le16_to_cpu(buff[0]), -def->range, def->range);
> + buff[1] = clamp_t(s16, le16_to_cpu(buff[1]), -def->range, def->range);
> + buff[2] = clamp_t(s16, le16_to_cpu(buff[2]), -def->range, def->range);
> +
> + iio_push_to_buffers_with_timestamp(indio_dev, buff, iio_get_time_ns());
> + goto exit;
Clearer to replicate the exit condition here I think and not have the goto.
> +
> +unlock:
> + mutex_unlock(&data->lock);
> + dev_err(&client->dev, "Error in reading axes block\n");
> +exit:
> + iio_trigger_notify_done(indio_dev->trig);
> + return IRQ_HANDLED;
> +}
> +
> static int ak8975_probe(struct i2c_client *client,
> const struct i2c_device_id *id)
> {
> @@ -867,9 +938,33 @@ static int ak8975_probe(struct i2c_client *client,
> indio_dev->dev.parent = &client->dev;
> indio_dev->channels = ak8975_channels;
> indio_dev->num_channels = ARRAY_SIZE(ak8975_channels);
> + indio_dev->available_scan_masks = ak8975_scan_masks;
> indio_dev->modes = INDIO_DIRECT_MODE;
> indio_dev->name = name;
> - return devm_iio_device_register(&client->dev, indio_dev);
> +
> + err = iio_triggered_buffer_setup(indio_dev, NULL, ak8975_handle_trigger,
> + NULL);
> + if (err) {
> + dev_err(&client->dev, "triggered buffer setup failed\n");
> + return err;
> + }
> +
> + err = iio_device_register(indio_dev);
> + if (!err)
> + return 0;
Please keep to convention of error paths being the non 'standard' route.
It adds a small amount of code, but gives slightly easier to read code.
> +
> + iio_triggered_buffer_cleanup(indio_dev);
> + dev_err(&client->dev, "device register failed\n");
> + return err;
> +}
> +
> +static int ak8975_remove(struct i2c_client *client)
> +{
> + struct iio_dev *indio_dev = i2c_get_clientdata(client);
> +
> + iio_device_unregister(indio_dev);
> + iio_triggered_buffer_cleanup(indio_dev);
blank line here preferred (nitpick of the day ;)
> + return 0;
> }
>
> static const struct i2c_device_id ak8975_id[] = {
> @@ -903,6 +998,7 @@ static struct i2c_driver ak8975_driver = {
> .acpi_match_table = ACPI_PTR(ak_acpi_match),
> },
> .probe = ak8975_probe,
> + .remove = ak8975_remove,
> .id_table = ak8975_id,
> };
> module_i2c_driver(ak8975_driver);
>
prev parent reply other threads:[~2016-03-05 15:45 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-03-03 10:44 [PATCH v2 0/5] iio:magnetometer:ak8975: fix and enhancements Gregor Boirie
2016-03-03 10:44 ` [PATCH v2 1/5] iio:magnetometer:ak8975: fix uninitialized chipset Gregor Boirie
2016-03-05 15:24 ` Jonathan Cameron
2016-03-03 10:44 ` [PATCH v2 2/5] iio:magnetometer:ak8975: remove unused field Gregor Boirie
2016-03-05 15:25 ` Jonathan Cameron
2016-03-03 10:44 ` [PATCH v2 3/5] iio:magnetometer:ak8975: power regulator support Gregor Boirie
2016-03-05 15:26 ` Jonathan Cameron
2016-03-03 10:44 ` [PATCH v2 4/5] iio:magnetometer:ak8975: mounting matrix support Gregor Boirie
2016-03-05 15:36 ` Jonathan Cameron
2016-03-09 10:56 ` Gregor Boirie
2016-03-09 20:46 ` Jonathan Cameron
2016-03-10 2:15 ` Rob Herring
2016-03-12 9:44 ` Jonathan Cameron
2016-03-14 17:19 ` Gregor Boirie
2016-03-15 21:56 ` Jonathan Cameron
2016-03-17 16:15 ` Gregor Boirie
2016-03-03 10:44 ` [PATCH v2 5/5] iio:magnetometer:ak8975: triggered buffer support Gregor Boirie
2016-03-05 15:45 ` Jonathan Cameron [this message]
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=56DAFF25.4080709@kernel.org \
--to=jic23@kernel.org \
--cc=Julia.Lawall@lip6.fr \
--cc=cristina.moraru09@gmail.com \
--cc=daniel.baluta@intel.com \
--cc=geert@linux-m68k.org \
--cc=gregor.boirie@parrot.com \
--cc=irina.tirdea@intel.com \
--cc=knaack.h@gmx.de \
--cc=lars@metafoo.de \
--cc=linux-iio@vger.kernel.org \
--cc=pmeerw@pmeerw.net \
/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;
as well as URLs for NNTP newsgroup(s).