From: Jonathan Cameron <jic23@kernel.org>
To: Peter Meerwald <pmeerw@pmeerw.net>
Cc: linux-iio@vger.kernel.org
Subject: Re: [PATCH 11/18] staging:iio:hmc5843: Add trigger handling
Date: Thu, 12 Sep 2013 23:01:39 +0100	[thread overview]
Message-ID: <523239C3.10508@kernel.org> (raw)
In-Reply-To: <1378170320-27538-12-git-send-email-pmeerw@pmeerw.net>
On 09/03/13 02:05, Peter Meerwald wrote:
> Signed-off-by: Peter Meerwald <pmeerw@pmeerw.net>
Couple of bits inline.  Basically, if you rely a little more on the core
handling of splitting out desired buffer elements then you can simplify
things somewhat.
> ---
>  drivers/staging/iio/magnetometer/hmc5843.c |   84 +++++++++++++++++++++++++---
>  1 file changed, 76 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c
> index 8a152c7..131ab8d 100644
> --- a/drivers/staging/iio/magnetometer/hmc5843.c
> +++ b/drivers/staging/iio/magnetometer/hmc5843.c
> @@ -23,6 +23,9 @@
>  #include <linux/i2c.h>
>  #include <linux/iio/iio.h>
>  #include <linux/iio/sysfs.h>
> +#include <linux/iio/trigger_consumer.h>
> +#include <linux/iio/buffer.h>
> +#include <linux/iio/triggered_buffer.h>
>  #include <linux/delay.h>
>
>  #define HMC5843_CONFIG_REG_A			0x00
> @@ -73,6 +76,9 @@ enum hmc5843_ids {
>  #define HMC5843_MEAS_CONF_NOT_USED		0x03
>  #define HMC5843_MEAS_CONF_MASK			0x03
>
> +/* 3 16-bit channels + padding + timestamp = 16 bytes */
> +#define HMC5843_BUFFER_SIZE 16
> +
>  /* Scaling factors: 10000000/Gain */
>  static const int hmc5843_regval_to_nanoscale[] = {
>  	6173, 7692, 10309, 12821, 18868, 21739, 25641, 35714
> @@ -174,6 +180,7 @@ struct hmc5843_data {
>  	u8 operating_mode;
>  	u8 range;
>  	const struct hmc5843_chip_info *variant;
If the channel demux is handled by the core, then just have
u16 buffer[8]; here.
> +	u16 *buffer;
>  };
>
>  /* The lower two bits contain the current conversion mode */
> @@ -453,7 +460,7 @@ static int hmc5843_read_raw(struct iio_dev *indio_dev,
>
>  	switch (mask) {
>  	case IIO_CHAN_INFO_RAW:
> -		return hmc5843_read_measurement(data, chan->address, val);
> +		return hmc5843_read_measurement(data, chan->scan_index, val);
>  	case IIO_CHAN_INFO_SCALE:
>  		*val = 0;
>  		*val2 = data->variant->regval_to_nanoscale[data->range];
> @@ -509,6 +516,47 @@ static int hmc5843_write_raw(struct iio_dev *indio_dev,
>  	}
>  }
>
> +static irqreturn_t hmc5843_trigger_handler(int irq, void *p)
> +{
> +	struct iio_poll_func *pf = p;
> +	struct iio_dev *indio_dev = pf->indio_dev;
> +	struct hmc5843_data *data = iio_priv(indio_dev);
> +	s64 time_ns = iio_get_time_ns();
Is this the right place to grab te timestamp?  Would immediately after
hmc5843_wait_measurement be closer to the actual capture time?
> +	int len = 0;
> +	int i, j = 0;
> +	s16 values[3];
> +	int ret;
> +
> +	mutex_lock(&data->lock);
> +	ret = hmc5843_wait_measurement(data);
> +	if (ret < 0) {
> +		mutex_unlock(&data->lock);
> +		goto done;
> +	}
> +
> +	ret = i2c_smbus_read_i2c_block_data(data->client,
> +		HMC5843_DATA_OUT_MSB_REGS, sizeof(values), (u8 *) values);
> +	mutex_unlock(&data->lock);
> +	if (ret < 0)
> +		goto done;
> +
> +	for_each_set_bit(i, indio_dev->active_scan_mask,
> +		indio_dev->masklength) {
> +		data->buffer[j++] = sign_extend32(be16_to_cpu(values[i]), 15);
> +		len += 2;
> +	}
This would be neater done by letting the demux code in the core handle it.
Hence just specify that the only possible scan mask is all channels (0x7)
as the only element in available_scan_masks, then always push the lot
onwards. Also as I read it you are extending to 32 bits. Why? You then
copy it into a 16 bit value neatly squashing it back to where you started
I think? Also, without this and with the core handling demux, you can
read directly into data->buffer and drop the copy.
static const int hmc5843_masks[] = { 0x3, 0};
indio_dev->available_scan_masks = hmc5843_masks;
(before registering the iio device) then
ret = i2c_smbus_read_i2c_block_data(data->client,
    HMC5843_DATA_OUT_MSB_REGS, 6, (u8 *) data->buffer);
in relevant place.
> +
> +	if (indio_dev->scan_timestamp)
> +		*(s64 *)((u8 *)data->buffer + ALIGN(len, sizeof(s64)))
> +			= time_ns;
> +	iio_push_to_buffers(indio_dev, (u8 *)data->buffer);
> +
> +done:
> +	iio_trigger_notify_done(indio_dev->trig);
> +
> +	return IRQ_HANDLED;
> +}
> +
>  #define HMC5843_CHANNEL(axis, idx)					\
>  	{								\
>  		.type = IIO_MAGN,					\
> @@ -518,13 +566,15 @@ static int hmc5843_write_raw(struct iio_dev *indio_dev,
>  		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |	\
>  			BIT(IIO_CHAN_INFO_SAMP_FREQ) |			\
>  			BIT(IIO_CHAN_INFO_CALIBSCALE),			\
> -		.address = idx						\
> +		.scan_index = idx,					\
> +		.scan_type = IIO_ST('s', 16, 16, 0),			\
>  	}
>
>  static const struct iio_chan_spec hmc5843_channels[] = {
>  	HMC5843_CHANNEL(X, 0),
>  	HMC5843_CHANNEL(Y, 1),
>  	HMC5843_CHANNEL(Z, 2),
> +	IIO_CHAN_SOFT_TIMESTAMP(3),
>  };
>
>  /* Beware: Y and Z are exchanged on HMC5883 */
> @@ -532,6 +582,7 @@ static const struct iio_chan_spec hmc5883_channels[] = {
>  	HMC5843_CHANNEL(X, 0),
>  	HMC5843_CHANNEL(Z, 1),
>  	HMC5843_CHANNEL(Y, 2),
> +	IIO_CHAN_SOFT_TIMESTAMP(3),
>  };
>
>  static struct attribute *hmc5843_attributes[] = {
> @@ -588,7 +639,7 @@ static int hmc5843_probe(struct i2c_client *client,
>  {
>  	struct hmc5843_data *data;
>  	struct iio_dev *indio_dev;
> -	int err = 0;
> +	int ret;
>
>  	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
>  	if (indio_dev == NULL)
> @@ -598,6 +649,10 @@ static int hmc5843_probe(struct i2c_client *client,
>  	data = iio_priv(indio_dev);
>  	data->client = client;
>  	data->variant = &hmc5843_chip_info_tbl[id->driver_data];
> +	data->buffer = devm_kzalloc(&client->dev, HMC5843_BUFFER_SIZE,
> +		GFP_KERNEL);
As suggested above, just allocate this directly as part of the buffer.
With i2c there are no buffer alignment requirements, but if you do have the
then there are ways to ensure you are cacheline aligned
(drivers/iio/adc/ad7266.c for example).  This is only needed for SPI (and is
why there are lots of allocations like the one you have here still kicking
about).
> +	if (data->buffer == NULL)
> +		return -ENOMEM;
>  	mutex_init(&data->lock);
>
>  	i2c_set_clientdata(client, indio_dev);
> @@ -606,20 +661,33 @@ static int hmc5843_probe(struct i2c_client *client,
>  	indio_dev->dev.parent = &client->dev;
>  	indio_dev->modes = INDIO_DIRECT_MODE;
>  	indio_dev->channels = data->variant->channels;
> -	indio_dev->num_channels = 3;
> +	indio_dev->num_channels = 4;
>
>  	hmc5843_init(data);
>
> -	err = iio_device_register(indio_dev);
> -	if (err)
> -		return err;
> +	ret = iio_triggered_buffer_setup(indio_dev, NULL,
> +		hmc5843_trigger_handler, NULL);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = iio_device_register(indio_dev);
> +	if (ret < 0)
> +		goto buffer_cleanup;
>
>  	return 0;
> +
> +buffer_cleanup:
> +	iio_triggered_buffer_cleanup(indio_dev);
> +	return ret;
>  }
>
>  static int hmc5843_remove(struct i2c_client *client)
>  {
> -	iio_device_unregister(i2c_get_clientdata(client));
> +	struct iio_dev *indio_dev = i2c_get_clientdata(client);
> +
> +	iio_device_unregister(indio_dev);
> +	iio_triggered_buffer_cleanup(indio_dev);
> +
>  	 /*  sleep mode to save power */
>  	hmc5843_configure(client, HMC5843_MODE_SLEEP);
>
>
next prev parent reply	other threads:[~2013-09-12 21:01 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-09-03  1:05 [PATCH 00/18] Cleanup hmc5843 magnetometer driver in staging Peter Meerwald
2013-09-03  1:05 ` [PATCH 01/18] staging:iio:hmc5843: Fix measurement conversion Peter Meerwald
2013-09-05 19:18   ` Lars-Peter Clausen
2013-09-11 21:57     ` Jonathan Cameron
2013-09-03  1:05 ` [PATCH 02/18] staging:iio:hmc5843: Use devm_iio_device_alloc Peter Meerwald
2013-09-11 22:02   ` Jonathan Cameron
2013-09-03  1:05 ` [PATCH 03/18] staging:iio:hmc5843: Add pointer to i2c client to data struct Peter Meerwald
2013-09-11 22:07   ` Jonathan Cameron
2013-09-03  1:05 ` [PATCH 04/18] staging:iio:hmc5843: Rewrite init function Peter Meerwald
2013-09-03  1:05 ` [PATCH 05/18] staging:iio:hmc5843: Use INFO_SAMP_FREQ Peter Meerwald
2013-09-03  1:05 ` [PATCH 06/18] staging:iio:hmc5843: Remove unused LSB register #defines Peter Meerwald
2013-09-03  1:05 ` [PATCH 07/18] staging:iio:hmc5843: Tighten comments Peter Meerwald
2013-09-03  1:05 ` [PATCH 08/18] staging:iio:hmc5843: Introduce helper functions to show/check list of int pairs Peter Meerwald
2013-09-03  1:05 ` [PATCH 09/18] staging:iio:hmc5843: Use CALIBSCALE instead of magn_range Peter Meerwald
2013-09-12 21:07   ` Jonathan Cameron
2013-09-03  1:05 ` [PATCH 10/18] staging:iio:hmc5843: Always read all channels values otherwise no updates Peter Meerwald
2013-09-03  1:05 ` [PATCH 11/18] staging:iio:hmc5843: Add trigger handling Peter Meerwald
2013-09-12 22:01   ` Jonathan Cameron [this message]
2013-09-03  1:05 ` [PATCH 12/18] staging:iio:hmc5843: Fix format of MODULE_AUTHOR's email Peter Meerwald
2013-09-03  1:05 ` [PATCH 13/18] staging:iio:hmc5843: Remove ability to change operating mode Peter Meerwald
2013-09-03  1:05 ` [PATCH 14/18] staging:iio:hmc5843: Rename _configure() to _set_mode() Peter Meerwald
2013-09-03  1:05 ` [PATCH 15/18] staging:iio:hmc5843: Reorganize _set_meas_conf() Peter Meerwald
2013-09-03  1:05 ` [PATCH 16/18] staging:iio:hmc5843: Rename _set_rate() to _set_samp_freq() Peter Meerwald
2013-09-03  1:05 ` [PATCH 17/18] staging:iio:hmc5843: Introduce _set_range_gain() Peter Meerwald
2013-09-03  1:05 ` [PATCH 18/18] staging:iio:hmc5843: Check initialization and chip identifier Peter Meerwald
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=523239C3.10508@kernel.org \
    --to=jic23@kernel.org \
    --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).