All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jonathan Cameron <jic23@kernel.org>
To: Martin Kepplinger <martink@posteo.de>,
	knaack.h@gmx.de, lars@metafoo.de, pmeerw@pmeerw.net,
	mfuzzey@parkeon.com, roberta.dobrescu@gmail.com,
	robh+dt@kernel.org, pawel.moll@arm.com, mark.rutland@arm.com,
	ijc+devicetree@hellion.org.uk, galak@codeaurora.org
Cc: devicetree@vger.kernel.org, linux-iio@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	christoph.muellner@theobroma-systems.com,
	Martin Kepplinger <martin.kepplinger@theobroma-systems.com>
Subject: Re: [PATCH 1/6] iio: mma8452: refactor for seperating chip specific data
Date: Sat, 5 Sep 2015 17:52:23 +0100	[thread overview]
Message-ID: <55EB1DC7.7090003@kernel.org> (raw)
In-Reply-To: <1441107913-4112-2-git-send-email-martink@posteo.de>

On 01/09/15 12:45, Martin Kepplinger wrote:
> This adds a struct mma_chip_info to hold data that will remain specific to
> the chip in use. It is provided during probe() and linked in
> struct of_device_id.
> 
> Also this suggests that the driver is called "mma8452" and now handles the
> MMA8452Q device, but is not limited to it.
> 
> Signed-off-by: Martin Kepplinger <martin.kepplinger@theobroma-systems.com>
> Signed-off-by: Christoph Muellner <christoph.muellner@theobroma-systems.com>
Looks very nice to me. Very clear resulting code.

Peter.  This is your driver so will give you time to take a look at this (or
tell me you don't want to / haven't got time if you like and I'll take
it as is!)

If we'd been towards the end of the cycle I might have gone with it without
waiting, but we have plenty of time now so lets not rush!

Jonathan
> ---
>  drivers/iio/accel/mma8452.c | 183 ++++++++++++++++++++++++++++++++------------
>  1 file changed, 134 insertions(+), 49 deletions(-)
> 
> diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c
> index b921d84..f28428fa 100644
> --- a/drivers/iio/accel/mma8452.c
> +++ b/drivers/iio/accel/mma8452.c
> @@ -22,6 +22,7 @@
>  #include <linux/iio/triggered_buffer.h>
>  #include <linux/iio/events.h>
>  #include <linux/delay.h>
> +#include <linux/of_device.h>
>  
>  #define MMA8452_STATUS				0x00
>  #define  MMA8452_STATUS_DRDY			(BIT(2) | BIT(1) | BIT(0))
> @@ -74,6 +75,52 @@ struct mma8452_data {
>  	struct mutex lock;
>  	u8 ctrl_reg1;
>  	u8 data_cfg;
> +	const struct mma_chip_info *chip_info;
> +};
> +
> +/**
> + * struct mma_chip_info - chip specific data for Freescale's accelerometers
> + * @chip_id:			WHO_AM_I register's value
> + * @channels:			struct iio_chan_spec matching the device's
> + *				capabilities
> + * @num_channels:		number of channels
> + * @mma_scales:			scale factors for converting register values
> + *				to m/s^2; 3 modes: 2g, 4g, 8g; 2 integers
> + *				per mode: m/s^2 and micro m/s^2
> + * @ev_cfg:			event config register address
> + * @ev_cfg_ele:			latch bit in event config register
> + * @ev_cfg_chan_shift:		number of the bit to enable events in X
> + *				direction; in event config register
> + * @ev_src:			event source register address
> + * @ev_src_xe:			bit in event source register that indicates
> + *				an event in X direction
> + * @ev_src_ye:			bit in event source register that indicates
> + *				an event in Y direction
> + * @ev_src_ze:			bit in event source register that indicates
> + *				an event in Z direction
> + * @ev_ths:			event threshold register address
> + * @ev_ths_mask:		mask for the threshold value
> + * @ev_count:			event count (period) register address
> + *
> + * Since not all chips supported by the driver support comparing high pass
> + * filtered data for events (interrupts), different interrupt sources are
> + * used for different chips and the relevant registers are included here.
> + */
> +struct mma_chip_info {
> +	u8 chip_id;
> +	const struct iio_chan_spec *channels;
> +	int num_channels;
> +	const int mma_scales[3][2];
> +	u8 ev_cfg;
> +	u8 ev_cfg_ele;
> +	u8 ev_cfg_chan_shift;
> +	u8 ev_src;
> +	u8 ev_src_xe;
> +	u8 ev_src_ye;
> +	u8 ev_src_ze;
> +	u8 ev_ths;
> +	u8 ev_ths_mask;
> +	u8 ev_count;
>  };
>  
>  static int mma8452_drdy(struct mma8452_data *data)
> @@ -143,16 +190,6 @@ static const int mma8452_samp_freq[8][2] = {
>  	{6, 250000}, {1, 560000}
>  };
>  
> -/*
> - * Hardware has fullscale of -2G, -4G, -8G corresponding to raw value -2048
> - * The userspace interface uses m/s^2 and we declare micro units
> - * So scale factor is given by:
> - *	g * N * 1000000 / 2048 for N = 2, 4, 8 and g = 9.80665
> - */
> -static const int mma8452_scales[3][2] = {
> -	{0, 9577}, {0, 19154}, {0, 38307}
> -};
> -
>  /* Datasheet table 35  (step time vs sample frequency) */
>  static const int mma8452_transient_time_step_us[8] = {
>  	1250,
> @@ -189,8 +226,11 @@ static ssize_t mma8452_show_scale_avail(struct device *dev,
>  					struct device_attribute *attr,
>  					char *buf)
>  {
> -	return mma8452_show_int_plus_micros(buf, mma8452_scales,
> -					    ARRAY_SIZE(mma8452_scales));
> +	struct mma8452_data *data = iio_priv(i2c_get_clientdata(
> +					     to_i2c_client(dev)));
> +
> +	return mma8452_show_int_plus_micros(buf, data->chip_info->mma_scales,
> +		ARRAY_SIZE(data->chip_info->mma_scales));
>  }
>  
>  static ssize_t mma8452_show_hp_cutoff_avail(struct device *dev,
> @@ -221,9 +261,8 @@ static int mma8452_get_samp_freq_index(struct mma8452_data *data,
>  
>  static int mma8452_get_scale_index(struct mma8452_data *data, int val, int val2)
>  {
> -	return mma8452_get_int_plus_micros_index(mma8452_scales,
> -						 ARRAY_SIZE(mma8452_scales),
> -						 val, val2);
> +	return mma8452_get_int_plus_micros_index(data->chip_info->mma_scales,
> +			ARRAY_SIZE(data->chip_info->mma_scales), val, val2);
>  }
>  
>  static int mma8452_get_hp_filter_index(struct mma8452_data *data,
> @@ -270,14 +309,15 @@ static int mma8452_read_raw(struct iio_dev *indio_dev,
>  		if (ret < 0)
>  			return ret;
>  
> -		*val = sign_extend32(be16_to_cpu(buffer[chan->scan_index]) >> 4,
> -				     11);
> +		*val = sign_extend32(be16_to_cpu(
> +			buffer[chan->scan_index]) >> chan->scan_type.shift,
> +			chan->scan_type.realbits - 1);
>  
>  		return IIO_VAL_INT;
>  	case IIO_CHAN_INFO_SCALE:
>  		i = data->data_cfg & MMA8452_DATA_CFG_FS_MASK;
> -		*val = mma8452_scales[i][0];
> -		*val2 = mma8452_scales[i][1];
> +		*val = data->chip_info->mma_scales[i][0];
> +		*val2 = data->chip_info->mma_scales[i][1];
>  
>  		return IIO_VAL_INT_PLUS_MICRO;
>  	case IIO_CHAN_INFO_SAMP_FREQ:
> @@ -439,17 +479,17 @@ static int mma8452_read_thresh(struct iio_dev *indio_dev,
>  	switch (info) {
>  	case IIO_EV_INFO_VALUE:
>  		ret = i2c_smbus_read_byte_data(data->client,
> -					       MMA8452_TRANSIENT_THS);
> +					       data->chip_info->ev_ths);
>  		if (ret < 0)
>  			return ret;
>  
> -		*val = ret & MMA8452_TRANSIENT_THS_MASK;
> +		*val = ret & data->chip_info->ev_ths_mask;
>  
>  		return IIO_VAL_INT;
>  
>  	case IIO_EV_INFO_PERIOD:
>  		ret = i2c_smbus_read_byte_data(data->client,
> -					       MMA8452_TRANSIENT_COUNT);
> +					       data->chip_info->ev_count);
>  		if (ret < 0)
>  			return ret;
>  
> @@ -497,7 +537,8 @@ static int mma8452_write_thresh(struct iio_dev *indio_dev,
>  		if (val < 0 || val > MMA8452_TRANSIENT_THS_MASK)
>  			return -EINVAL;
>  
> -		return mma8452_change_config(data, MMA8452_TRANSIENT_THS, val);
> +		return mma8452_change_config(data, data->chip_info->ev_ths,
> +					     val);
>  
>  	case IIO_EV_INFO_PERIOD:
>  		steps = (val * USEC_PER_SEC + val2) /
> @@ -507,7 +548,7 @@ static int mma8452_write_thresh(struct iio_dev *indio_dev,
>  		if (steps < 0 || steps > 0xff)
>  			return -EINVAL;
>  
> -		return mma8452_change_config(data, MMA8452_TRANSIENT_COUNT,
> +		return mma8452_change_config(data, data->chip_info->ev_count,
>  					     steps);
>  
>  	case IIO_EV_INFO_HIGH_PASS_FILTER_3DB:
> @@ -538,13 +579,15 @@ static int mma8452_read_event_config(struct iio_dev *indio_dev,
>  				     enum iio_event_direction dir)
>  {
>  	struct mma8452_data *data = iio_priv(indio_dev);
> +	const struct mma_chip_info *chip = data->chip_info;
>  	int ret;
>  
> -	ret = i2c_smbus_read_byte_data(data->client, MMA8452_TRANSIENT_CFG);
> +	ret = i2c_smbus_read_byte_data(data->client,
> +				       data->chip_info->ev_cfg);
>  	if (ret < 0)
>  		return ret;
>  
> -	return ret & MMA8452_TRANSIENT_CFG_CHAN(chan->scan_index) ? 1 : 0;
> +	return !!(ret & BIT(chan->scan_index + chip->ev_cfg_chan_shift));
>  }
>  
>  static int mma8452_write_event_config(struct iio_dev *indio_dev,
> @@ -554,20 +597,21 @@ static int mma8452_write_event_config(struct iio_dev *indio_dev,
>  				      int state)
>  {
>  	struct mma8452_data *data = iio_priv(indio_dev);
> +	const struct mma_chip_info *chip = data->chip_info;
>  	int val;
>  
> -	val = i2c_smbus_read_byte_data(data->client, MMA8452_TRANSIENT_CFG);
> +	val = i2c_smbus_read_byte_data(data->client, chip->ev_cfg);
>  	if (val < 0)
>  		return val;
>  
>  	if (state)
> -		val |= MMA8452_TRANSIENT_CFG_CHAN(chan->scan_index);
> +		val |= BIT(chan->scan_index + chip->ev_cfg_chan_shift);
>  	else
> -		val &= ~MMA8452_TRANSIENT_CFG_CHAN(chan->scan_index);
> +		val &= ~BIT(chan->scan_index + chip->ev_cfg_chan_shift);
>  
>  	val |= MMA8452_TRANSIENT_CFG_ELE;
>  
> -	return mma8452_change_config(data, MMA8452_TRANSIENT_CFG, val);
> +	return mma8452_change_config(data, chip->ev_cfg, val);
>  }
>  
>  static void mma8452_transient_interrupt(struct iio_dev *indio_dev)
> @@ -576,25 +620,25 @@ static void mma8452_transient_interrupt(struct iio_dev *indio_dev)
>  	s64 ts = iio_get_time_ns();
>  	int src;
>  
> -	src = i2c_smbus_read_byte_data(data->client, MMA8452_TRANSIENT_SRC);
> +	src = i2c_smbus_read_byte_data(data->client, data->chip_info->ev_src);
>  	if (src < 0)
>  		return;
>  
> -	if (src & MMA8452_TRANSIENT_SRC_XTRANSE)
> +	if (src & data->chip_info->ev_src_xe)
>  		iio_push_event(indio_dev,
>  			       IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X,
>  						  IIO_EV_TYPE_MAG,
>  						  IIO_EV_DIR_RISING),
>  			       ts);
>  
> -	if (src & MMA8452_TRANSIENT_SRC_YTRANSE)
> +	if (src & data->chip_info->ev_src_ye)
>  		iio_push_event(indio_dev,
>  			       IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_Y,
>  						  IIO_EV_TYPE_MAG,
>  						  IIO_EV_DIR_RISING),
>  			       ts);
>  
> -	if (src & MMA8452_TRANSIENT_SRC_ZTRANSE)
> +	if (src & data->chip_info->ev_src_ze)
>  		iio_push_event(indio_dev,
>  			       IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_Z,
>  						  IIO_EV_TYPE_MAG,
> @@ -696,7 +740,7 @@ static struct attribute_group mma8452_event_attribute_group = {
>  	.name = "events",
>  };
>  
> -#define MMA8452_CHANNEL(axis, idx) { \
> +#define MMA8452_CHANNEL(axis, idx, bits) { \
>  	.type = IIO_ACCEL, \
>  	.modified = 1, \
>  	.channel2 = IIO_MOD_##axis, \
> @@ -708,9 +752,9 @@ static struct attribute_group mma8452_event_attribute_group = {
>  	.scan_index = idx, \
>  	.scan_type = { \
>  		.sign = 's', \
> -		.realbits = 12, \
> +		.realbits = (bits), \
>  		.storagebits = 16, \
> -		.shift = 4, \
> +		.shift = 16 - (bits), \
>  		.endianness = IIO_BE, \
>  	}, \
>  	.event_spec = mma8452_transient_event, \
> @@ -718,12 +762,42 @@ static struct attribute_group mma8452_event_attribute_group = {
>  }
>  
>  static const struct iio_chan_spec mma8452_channels[] = {
> -	MMA8452_CHANNEL(X, 0),
> -	MMA8452_CHANNEL(Y, 1),
> -	MMA8452_CHANNEL(Z, 2),
> +	MMA8452_CHANNEL(X, 0, 12),
> +	MMA8452_CHANNEL(Y, 1, 12),
> +	MMA8452_CHANNEL(Z, 2, 12),
>  	IIO_CHAN_SOFT_TIMESTAMP(3),
>  };
>  
> +enum {
> +	mma8452,
> +};
> +
> +static const struct mma_chip_info mma_chip_info_table[] = {
> +	[mma8452] = {
> +		.chip_id = MMA8452_DEVICE_ID,
> +		.channels = mma8452_channels,
> +		.num_channels = ARRAY_SIZE(mma8452_channels),
> +		/*
> +		 * Hardware has fullscale of -2G, -4G, -8G corresponding to
> +		 * raw value -2048 for 12 bit or -512 for 10 bit.
> +		 * The userspace interface uses m/s^2 and we declare micro units
> +		 * So scale factor for 12 bit here is given by:
> +		 *	g * N * 1000000 / 2048 for N = 2, 4, 8 and g=9.80665
> +		 */
> +		.mma_scales = { {0, 9577}, {0, 19154}, {0, 38307} },
> +		.ev_cfg = MMA8452_TRANSIENT_CFG,
> +		.ev_cfg_ele = MMA8452_TRANSIENT_CFG_ELE,
> +		.ev_cfg_chan_shift = 1,
> +		.ev_src = MMA8452_TRANSIENT_SRC,
> +		.ev_src_xe = MMA8452_TRANSIENT_SRC_XTRANSE,
> +		.ev_src_ye = MMA8452_TRANSIENT_SRC_YTRANSE,
> +		.ev_src_ze = MMA8452_TRANSIENT_SRC_ZTRANSE,
> +		.ev_ths = MMA8452_TRANSIENT_THS,
> +		.ev_ths_mask = MMA8452_TRANSIENT_THS_MASK,
> +		.ev_count = MMA8452_TRANSIENT_COUNT,
> +	},
> +};
> +
>  static struct attribute *mma8452_attributes[] = {
>  	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
>  	&iio_dev_attr_in_accel_scale_available.dev_attr.attr,
> @@ -841,12 +915,19 @@ static int mma8452_reset(struct i2c_client *client)
>  	return -ETIMEDOUT;
>  }
>  
> +static const struct of_device_id mma8452_dt_ids[] = {
> +	{ .compatible = "fsl,mma8452", .data = &mma_chip_info_table[mma8452] },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, mma8452_dt_ids);
> +
>  static int mma8452_probe(struct i2c_client *client,
>  			 const struct i2c_device_id *id)
>  {
>  	struct mma8452_data *data;
>  	struct iio_dev *indio_dev;
>  	int ret;
> +	const struct of_device_id *match;
>  
>  	ret = i2c_smbus_read_byte_data(client, MMA8452_WHO_AM_I);
>  	if (ret < 0)
> @@ -854,6 +935,12 @@ static int mma8452_probe(struct i2c_client *client,
>  	if (ret != MMA8452_DEVICE_ID)
>  		return -ENODEV;
>  
> +	match = of_match_device(mma8452_dt_ids, &client->dev);
> +	if (!match) {
> +		dev_err(&client->dev, "unknown device model\n");
> +		return -ENODEV;
> +	}
> +
>  	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
>  	if (!indio_dev)
>  		return -ENOMEM;
> @@ -861,14 +948,18 @@ static int mma8452_probe(struct i2c_client *client,
>  	data = iio_priv(indio_dev);
>  	data->client = client;
>  	mutex_init(&data->lock);
> +	data->chip_info = match->data;
> +
> +	dev_info(&client->dev, "registering %s accelerometer; ID 0x%x\n",
> +		 match->compatible, data->chip_info->chip_id);
>  
>  	i2c_set_clientdata(client, indio_dev);
>  	indio_dev->info = &mma8452_info;
>  	indio_dev->name = id->name;
>  	indio_dev->dev.parent = &client->dev;
>  	indio_dev->modes = INDIO_DIRECT_MODE;
> -	indio_dev->channels = mma8452_channels;
> -	indio_dev->num_channels = ARRAY_SIZE(mma8452_channels);
> +	indio_dev->channels = data->chip_info->channels;
> +	indio_dev->num_channels = data->chip_info->num_channels;
>  	indio_dev->available_scan_masks = mma8452_scan_masks;
>  
>  	ret = mma8452_reset(client);
> @@ -987,17 +1078,11 @@ static SIMPLE_DEV_PM_OPS(mma8452_pm_ops, mma8452_suspend, mma8452_resume);
>  #endif
>  
>  static const struct i2c_device_id mma8452_id[] = {
> -	{ "mma8452", 0 },
> +	{ "mma8452", mma8452 },
>  	{ }
>  };
>  MODULE_DEVICE_TABLE(i2c, mma8452_id);
>  
> -static const struct of_device_id mma8452_dt_ids[] = {
> -	{ .compatible = "fsl,mma8452" },
> -	{ }
> -};
> -MODULE_DEVICE_TABLE(of, mma8452_dt_ids);
> -
>  static struct i2c_driver mma8452_driver = {
>  	.driver = {
>  		.name	= "mma8452",
> 


WARNING: multiple messages have this Message-ID (diff)
From: Jonathan Cameron <jic23-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
To: Martin Kepplinger
	<martink-1KBjaw7Xf1+zQB+pC5nmwQ@public.gmane.org>,
	knaack.h-Mmb7MZpHnFY@public.gmane.org,
	lars-Qo5EllUWu/uELgA04lAiVw@public.gmane.org,
	pmeerw-jW+XmwGofnusTnJN9+BGXg@public.gmane.org,
	mfuzzey-mB3Nsq4MPf1BDgjK7y7TUQ@public.gmane.org,
	roberta.dobrescu-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org,
	pawel.moll-5wv7dgnIgG8@public.gmane.org,
	mark.rutland-5wv7dgnIgG8@public.gmane.org,
	ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg@public.gmane.org,
	galak-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-iio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	christoph.muellner-SN7IsUiht6C/RdPyistoZJqQE7yCjDx5@public.gmane.org,
	Martin Kepplinger
	<martin.kepplinger-SN7IsUiht6C/RdPyistoZJqQE7yCjDx5@public.gmane.org>
Subject: Re: [PATCH 1/6] iio: mma8452: refactor for seperating chip specific data
Date: Sat, 5 Sep 2015 17:52:23 +0100	[thread overview]
Message-ID: <55EB1DC7.7090003@kernel.org> (raw)
In-Reply-To: <1441107913-4112-2-git-send-email-martink-1KBjaw7Xf1+zQB+pC5nmwQ@public.gmane.org>

On 01/09/15 12:45, Martin Kepplinger wrote:
> This adds a struct mma_chip_info to hold data that will remain specific to
> the chip in use. It is provided during probe() and linked in
> struct of_device_id.
> 
> Also this suggests that the driver is called "mma8452" and now handles the
> MMA8452Q device, but is not limited to it.
> 
> Signed-off-by: Martin Kepplinger <martin.kepplinger-SN7IsUiht6C/RdPyistoZJqQE7yCjDx5@public.gmane.org>
> Signed-off-by: Christoph Muellner <christoph.muellner-SN7IsUiht6C/RdPyistoZJqQE7yCjDx5@public.gmane.org>
Looks very nice to me. Very clear resulting code.

Peter.  This is your driver so will give you time to take a look at this (or
tell me you don't want to / haven't got time if you like and I'll take
it as is!)

If we'd been towards the end of the cycle I might have gone with it without
waiting, but we have plenty of time now so lets not rush!

Jonathan
> ---
>  drivers/iio/accel/mma8452.c | 183 ++++++++++++++++++++++++++++++++------------
>  1 file changed, 134 insertions(+), 49 deletions(-)
> 
> diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c
> index b921d84..f28428fa 100644
> --- a/drivers/iio/accel/mma8452.c
> +++ b/drivers/iio/accel/mma8452.c
> @@ -22,6 +22,7 @@
>  #include <linux/iio/triggered_buffer.h>
>  #include <linux/iio/events.h>
>  #include <linux/delay.h>
> +#include <linux/of_device.h>
>  
>  #define MMA8452_STATUS				0x00
>  #define  MMA8452_STATUS_DRDY			(BIT(2) | BIT(1) | BIT(0))
> @@ -74,6 +75,52 @@ struct mma8452_data {
>  	struct mutex lock;
>  	u8 ctrl_reg1;
>  	u8 data_cfg;
> +	const struct mma_chip_info *chip_info;
> +};
> +
> +/**
> + * struct mma_chip_info - chip specific data for Freescale's accelerometers
> + * @chip_id:			WHO_AM_I register's value
> + * @channels:			struct iio_chan_spec matching the device's
> + *				capabilities
> + * @num_channels:		number of channels
> + * @mma_scales:			scale factors for converting register values
> + *				to m/s^2; 3 modes: 2g, 4g, 8g; 2 integers
> + *				per mode: m/s^2 and micro m/s^2
> + * @ev_cfg:			event config register address
> + * @ev_cfg_ele:			latch bit in event config register
> + * @ev_cfg_chan_shift:		number of the bit to enable events in X
> + *				direction; in event config register
> + * @ev_src:			event source register address
> + * @ev_src_xe:			bit in event source register that indicates
> + *				an event in X direction
> + * @ev_src_ye:			bit in event source register that indicates
> + *				an event in Y direction
> + * @ev_src_ze:			bit in event source register that indicates
> + *				an event in Z direction
> + * @ev_ths:			event threshold register address
> + * @ev_ths_mask:		mask for the threshold value
> + * @ev_count:			event count (period) register address
> + *
> + * Since not all chips supported by the driver support comparing high pass
> + * filtered data for events (interrupts), different interrupt sources are
> + * used for different chips and the relevant registers are included here.
> + */
> +struct mma_chip_info {
> +	u8 chip_id;
> +	const struct iio_chan_spec *channels;
> +	int num_channels;
> +	const int mma_scales[3][2];
> +	u8 ev_cfg;
> +	u8 ev_cfg_ele;
> +	u8 ev_cfg_chan_shift;
> +	u8 ev_src;
> +	u8 ev_src_xe;
> +	u8 ev_src_ye;
> +	u8 ev_src_ze;
> +	u8 ev_ths;
> +	u8 ev_ths_mask;
> +	u8 ev_count;
>  };
>  
>  static int mma8452_drdy(struct mma8452_data *data)
> @@ -143,16 +190,6 @@ static const int mma8452_samp_freq[8][2] = {
>  	{6, 250000}, {1, 560000}
>  };
>  
> -/*
> - * Hardware has fullscale of -2G, -4G, -8G corresponding to raw value -2048
> - * The userspace interface uses m/s^2 and we declare micro units
> - * So scale factor is given by:
> - *	g * N * 1000000 / 2048 for N = 2, 4, 8 and g = 9.80665
> - */
> -static const int mma8452_scales[3][2] = {
> -	{0, 9577}, {0, 19154}, {0, 38307}
> -};
> -
>  /* Datasheet table 35  (step time vs sample frequency) */
>  static const int mma8452_transient_time_step_us[8] = {
>  	1250,
> @@ -189,8 +226,11 @@ static ssize_t mma8452_show_scale_avail(struct device *dev,
>  					struct device_attribute *attr,
>  					char *buf)
>  {
> -	return mma8452_show_int_plus_micros(buf, mma8452_scales,
> -					    ARRAY_SIZE(mma8452_scales));
> +	struct mma8452_data *data = iio_priv(i2c_get_clientdata(
> +					     to_i2c_client(dev)));
> +
> +	return mma8452_show_int_plus_micros(buf, data->chip_info->mma_scales,
> +		ARRAY_SIZE(data->chip_info->mma_scales));
>  }
>  
>  static ssize_t mma8452_show_hp_cutoff_avail(struct device *dev,
> @@ -221,9 +261,8 @@ static int mma8452_get_samp_freq_index(struct mma8452_data *data,
>  
>  static int mma8452_get_scale_index(struct mma8452_data *data, int val, int val2)
>  {
> -	return mma8452_get_int_plus_micros_index(mma8452_scales,
> -						 ARRAY_SIZE(mma8452_scales),
> -						 val, val2);
> +	return mma8452_get_int_plus_micros_index(data->chip_info->mma_scales,
> +			ARRAY_SIZE(data->chip_info->mma_scales), val, val2);
>  }
>  
>  static int mma8452_get_hp_filter_index(struct mma8452_data *data,
> @@ -270,14 +309,15 @@ static int mma8452_read_raw(struct iio_dev *indio_dev,
>  		if (ret < 0)
>  			return ret;
>  
> -		*val = sign_extend32(be16_to_cpu(buffer[chan->scan_index]) >> 4,
> -				     11);
> +		*val = sign_extend32(be16_to_cpu(
> +			buffer[chan->scan_index]) >> chan->scan_type.shift,
> +			chan->scan_type.realbits - 1);
>  
>  		return IIO_VAL_INT;
>  	case IIO_CHAN_INFO_SCALE:
>  		i = data->data_cfg & MMA8452_DATA_CFG_FS_MASK;
> -		*val = mma8452_scales[i][0];
> -		*val2 = mma8452_scales[i][1];
> +		*val = data->chip_info->mma_scales[i][0];
> +		*val2 = data->chip_info->mma_scales[i][1];
>  
>  		return IIO_VAL_INT_PLUS_MICRO;
>  	case IIO_CHAN_INFO_SAMP_FREQ:
> @@ -439,17 +479,17 @@ static int mma8452_read_thresh(struct iio_dev *indio_dev,
>  	switch (info) {
>  	case IIO_EV_INFO_VALUE:
>  		ret = i2c_smbus_read_byte_data(data->client,
> -					       MMA8452_TRANSIENT_THS);
> +					       data->chip_info->ev_ths);
>  		if (ret < 0)
>  			return ret;
>  
> -		*val = ret & MMA8452_TRANSIENT_THS_MASK;
> +		*val = ret & data->chip_info->ev_ths_mask;
>  
>  		return IIO_VAL_INT;
>  
>  	case IIO_EV_INFO_PERIOD:
>  		ret = i2c_smbus_read_byte_data(data->client,
> -					       MMA8452_TRANSIENT_COUNT);
> +					       data->chip_info->ev_count);
>  		if (ret < 0)
>  			return ret;
>  
> @@ -497,7 +537,8 @@ static int mma8452_write_thresh(struct iio_dev *indio_dev,
>  		if (val < 0 || val > MMA8452_TRANSIENT_THS_MASK)
>  			return -EINVAL;
>  
> -		return mma8452_change_config(data, MMA8452_TRANSIENT_THS, val);
> +		return mma8452_change_config(data, data->chip_info->ev_ths,
> +					     val);
>  
>  	case IIO_EV_INFO_PERIOD:
>  		steps = (val * USEC_PER_SEC + val2) /
> @@ -507,7 +548,7 @@ static int mma8452_write_thresh(struct iio_dev *indio_dev,
>  		if (steps < 0 || steps > 0xff)
>  			return -EINVAL;
>  
> -		return mma8452_change_config(data, MMA8452_TRANSIENT_COUNT,
> +		return mma8452_change_config(data, data->chip_info->ev_count,
>  					     steps);
>  
>  	case IIO_EV_INFO_HIGH_PASS_FILTER_3DB:
> @@ -538,13 +579,15 @@ static int mma8452_read_event_config(struct iio_dev *indio_dev,
>  				     enum iio_event_direction dir)
>  {
>  	struct mma8452_data *data = iio_priv(indio_dev);
> +	const struct mma_chip_info *chip = data->chip_info;
>  	int ret;
>  
> -	ret = i2c_smbus_read_byte_data(data->client, MMA8452_TRANSIENT_CFG);
> +	ret = i2c_smbus_read_byte_data(data->client,
> +				       data->chip_info->ev_cfg);
>  	if (ret < 0)
>  		return ret;
>  
> -	return ret & MMA8452_TRANSIENT_CFG_CHAN(chan->scan_index) ? 1 : 0;
> +	return !!(ret & BIT(chan->scan_index + chip->ev_cfg_chan_shift));
>  }
>  
>  static int mma8452_write_event_config(struct iio_dev *indio_dev,
> @@ -554,20 +597,21 @@ static int mma8452_write_event_config(struct iio_dev *indio_dev,
>  				      int state)
>  {
>  	struct mma8452_data *data = iio_priv(indio_dev);
> +	const struct mma_chip_info *chip = data->chip_info;
>  	int val;
>  
> -	val = i2c_smbus_read_byte_data(data->client, MMA8452_TRANSIENT_CFG);
> +	val = i2c_smbus_read_byte_data(data->client, chip->ev_cfg);
>  	if (val < 0)
>  		return val;
>  
>  	if (state)
> -		val |= MMA8452_TRANSIENT_CFG_CHAN(chan->scan_index);
> +		val |= BIT(chan->scan_index + chip->ev_cfg_chan_shift);
>  	else
> -		val &= ~MMA8452_TRANSIENT_CFG_CHAN(chan->scan_index);
> +		val &= ~BIT(chan->scan_index + chip->ev_cfg_chan_shift);
>  
>  	val |= MMA8452_TRANSIENT_CFG_ELE;
>  
> -	return mma8452_change_config(data, MMA8452_TRANSIENT_CFG, val);
> +	return mma8452_change_config(data, chip->ev_cfg, val);
>  }
>  
>  static void mma8452_transient_interrupt(struct iio_dev *indio_dev)
> @@ -576,25 +620,25 @@ static void mma8452_transient_interrupt(struct iio_dev *indio_dev)
>  	s64 ts = iio_get_time_ns();
>  	int src;
>  
> -	src = i2c_smbus_read_byte_data(data->client, MMA8452_TRANSIENT_SRC);
> +	src = i2c_smbus_read_byte_data(data->client, data->chip_info->ev_src);
>  	if (src < 0)
>  		return;
>  
> -	if (src & MMA8452_TRANSIENT_SRC_XTRANSE)
> +	if (src & data->chip_info->ev_src_xe)
>  		iio_push_event(indio_dev,
>  			       IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X,
>  						  IIO_EV_TYPE_MAG,
>  						  IIO_EV_DIR_RISING),
>  			       ts);
>  
> -	if (src & MMA8452_TRANSIENT_SRC_YTRANSE)
> +	if (src & data->chip_info->ev_src_ye)
>  		iio_push_event(indio_dev,
>  			       IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_Y,
>  						  IIO_EV_TYPE_MAG,
>  						  IIO_EV_DIR_RISING),
>  			       ts);
>  
> -	if (src & MMA8452_TRANSIENT_SRC_ZTRANSE)
> +	if (src & data->chip_info->ev_src_ze)
>  		iio_push_event(indio_dev,
>  			       IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_Z,
>  						  IIO_EV_TYPE_MAG,
> @@ -696,7 +740,7 @@ static struct attribute_group mma8452_event_attribute_group = {
>  	.name = "events",
>  };
>  
> -#define MMA8452_CHANNEL(axis, idx) { \
> +#define MMA8452_CHANNEL(axis, idx, bits) { \
>  	.type = IIO_ACCEL, \
>  	.modified = 1, \
>  	.channel2 = IIO_MOD_##axis, \
> @@ -708,9 +752,9 @@ static struct attribute_group mma8452_event_attribute_group = {
>  	.scan_index = idx, \
>  	.scan_type = { \
>  		.sign = 's', \
> -		.realbits = 12, \
> +		.realbits = (bits), \
>  		.storagebits = 16, \
> -		.shift = 4, \
> +		.shift = 16 - (bits), \
>  		.endianness = IIO_BE, \
>  	}, \
>  	.event_spec = mma8452_transient_event, \
> @@ -718,12 +762,42 @@ static struct attribute_group mma8452_event_attribute_group = {
>  }
>  
>  static const struct iio_chan_spec mma8452_channels[] = {
> -	MMA8452_CHANNEL(X, 0),
> -	MMA8452_CHANNEL(Y, 1),
> -	MMA8452_CHANNEL(Z, 2),
> +	MMA8452_CHANNEL(X, 0, 12),
> +	MMA8452_CHANNEL(Y, 1, 12),
> +	MMA8452_CHANNEL(Z, 2, 12),
>  	IIO_CHAN_SOFT_TIMESTAMP(3),
>  };
>  
> +enum {
> +	mma8452,
> +};
> +
> +static const struct mma_chip_info mma_chip_info_table[] = {
> +	[mma8452] = {
> +		.chip_id = MMA8452_DEVICE_ID,
> +		.channels = mma8452_channels,
> +		.num_channels = ARRAY_SIZE(mma8452_channels),
> +		/*
> +		 * Hardware has fullscale of -2G, -4G, -8G corresponding to
> +		 * raw value -2048 for 12 bit or -512 for 10 bit.
> +		 * The userspace interface uses m/s^2 and we declare micro units
> +		 * So scale factor for 12 bit here is given by:
> +		 *	g * N * 1000000 / 2048 for N = 2, 4, 8 and g=9.80665
> +		 */
> +		.mma_scales = { {0, 9577}, {0, 19154}, {0, 38307} },
> +		.ev_cfg = MMA8452_TRANSIENT_CFG,
> +		.ev_cfg_ele = MMA8452_TRANSIENT_CFG_ELE,
> +		.ev_cfg_chan_shift = 1,
> +		.ev_src = MMA8452_TRANSIENT_SRC,
> +		.ev_src_xe = MMA8452_TRANSIENT_SRC_XTRANSE,
> +		.ev_src_ye = MMA8452_TRANSIENT_SRC_YTRANSE,
> +		.ev_src_ze = MMA8452_TRANSIENT_SRC_ZTRANSE,
> +		.ev_ths = MMA8452_TRANSIENT_THS,
> +		.ev_ths_mask = MMA8452_TRANSIENT_THS_MASK,
> +		.ev_count = MMA8452_TRANSIENT_COUNT,
> +	},
> +};
> +
>  static struct attribute *mma8452_attributes[] = {
>  	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
>  	&iio_dev_attr_in_accel_scale_available.dev_attr.attr,
> @@ -841,12 +915,19 @@ static int mma8452_reset(struct i2c_client *client)
>  	return -ETIMEDOUT;
>  }
>  
> +static const struct of_device_id mma8452_dt_ids[] = {
> +	{ .compatible = "fsl,mma8452", .data = &mma_chip_info_table[mma8452] },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, mma8452_dt_ids);
> +
>  static int mma8452_probe(struct i2c_client *client,
>  			 const struct i2c_device_id *id)
>  {
>  	struct mma8452_data *data;
>  	struct iio_dev *indio_dev;
>  	int ret;
> +	const struct of_device_id *match;
>  
>  	ret = i2c_smbus_read_byte_data(client, MMA8452_WHO_AM_I);
>  	if (ret < 0)
> @@ -854,6 +935,12 @@ static int mma8452_probe(struct i2c_client *client,
>  	if (ret != MMA8452_DEVICE_ID)
>  		return -ENODEV;
>  
> +	match = of_match_device(mma8452_dt_ids, &client->dev);
> +	if (!match) {
> +		dev_err(&client->dev, "unknown device model\n");
> +		return -ENODEV;
> +	}
> +
>  	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
>  	if (!indio_dev)
>  		return -ENOMEM;
> @@ -861,14 +948,18 @@ static int mma8452_probe(struct i2c_client *client,
>  	data = iio_priv(indio_dev);
>  	data->client = client;
>  	mutex_init(&data->lock);
> +	data->chip_info = match->data;
> +
> +	dev_info(&client->dev, "registering %s accelerometer; ID 0x%x\n",
> +		 match->compatible, data->chip_info->chip_id);
>  
>  	i2c_set_clientdata(client, indio_dev);
>  	indio_dev->info = &mma8452_info;
>  	indio_dev->name = id->name;
>  	indio_dev->dev.parent = &client->dev;
>  	indio_dev->modes = INDIO_DIRECT_MODE;
> -	indio_dev->channels = mma8452_channels;
> -	indio_dev->num_channels = ARRAY_SIZE(mma8452_channels);
> +	indio_dev->channels = data->chip_info->channels;
> +	indio_dev->num_channels = data->chip_info->num_channels;
>  	indio_dev->available_scan_masks = mma8452_scan_masks;
>  
>  	ret = mma8452_reset(client);
> @@ -987,17 +1078,11 @@ static SIMPLE_DEV_PM_OPS(mma8452_pm_ops, mma8452_suspend, mma8452_resume);
>  #endif
>  
>  static const struct i2c_device_id mma8452_id[] = {
> -	{ "mma8452", 0 },
> +	{ "mma8452", mma8452 },
>  	{ }
>  };
>  MODULE_DEVICE_TABLE(i2c, mma8452_id);
>  
> -static const struct of_device_id mma8452_dt_ids[] = {
> -	{ .compatible = "fsl,mma8452" },
> -	{ }
> -};
> -MODULE_DEVICE_TABLE(of, mma8452_dt_ids);
> -
>  static struct i2c_driver mma8452_driver = {
>  	.driver = {
>  		.name	= "mma8452",
> 

  reply	other threads:[~2015-09-05 16:52 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-09-01 11:45 [PATCHv6 0/6] iio: mma8452: improve driver and support more chips Martin Kepplinger
2015-09-01 11:45 ` Martin Kepplinger
2015-09-01 11:45 ` [PATCH 1/6] iio: mma8452: refactor for seperating chip specific data Martin Kepplinger
2015-09-05 16:52   ` Jonathan Cameron [this message]
2015-09-05 16:52     ` Jonathan Cameron
2015-09-12 10:07   ` Jonathan Cameron
2015-09-12 10:07     ` Jonathan Cameron
2015-09-01 11:45 ` [PATCH 2/6] iio: mma8452: add support for MMA8453Q accelerometer chip Martin Kepplinger
2015-09-05 16:56   ` Jonathan Cameron
2015-09-05 16:56     ` Jonathan Cameron
2015-09-12 10:07   ` Jonathan Cameron
2015-09-12 10:07     ` Jonathan Cameron
2015-09-01 11:45 ` [PATCH 3/6] iio: mma8452: add freefall / motion interrupt source Martin Kepplinger
2015-09-05 16:58   ` Jonathan Cameron
2015-09-05 16:58     ` Jonathan Cameron
2015-09-12 10:08   ` Jonathan Cameron
2015-09-12 10:08     ` Jonathan Cameron
2015-09-01 11:45 ` [PATCH 4/6] iio: mma8452: add support for MMA8652FC and MMA8653FC Martin Kepplinger
2015-09-01 11:45   ` Martin Kepplinger
2015-09-05 17:05   ` Jonathan Cameron
2015-09-05 17:05     ` Jonathan Cameron
2015-09-12 10:08   ` Jonathan Cameron
2015-09-12 10:08     ` Jonathan Cameron
2015-09-01 11:45 ` [PATCH 5/6] iio: mma8452: add copyright notice comment Martin Kepplinger
2015-09-01 11:45   ` Martin Kepplinger
2015-09-12 10:09   ` Jonathan Cameron
2015-09-12 10:09     ` Jonathan Cameron
2015-09-01 11:45 ` [PATCH 6/6] iio: mma8452: leave sysfs namings to the iio core Martin Kepplinger
2015-09-01 11:45   ` Martin Kepplinger
2015-09-05 17:07   ` Jonathan Cameron
2015-09-05 17:07     ` Jonathan Cameron
2015-09-12 10:09   ` Jonathan Cameron
2015-09-12 10:09     ` Jonathan Cameron

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=55EB1DC7.7090003@kernel.org \
    --to=jic23@kernel.org \
    --cc=christoph.muellner@theobroma-systems.com \
    --cc=devicetree@vger.kernel.org \
    --cc=galak@codeaurora.org \
    --cc=ijc+devicetree@hellion.org.uk \
    --cc=knaack.h@gmx.de \
    --cc=lars@metafoo.de \
    --cc=linux-iio@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=martin.kepplinger@theobroma-systems.com \
    --cc=martink@posteo.de \
    --cc=mfuzzey@parkeon.com \
    --cc=pawel.moll@arm.com \
    --cc=pmeerw@pmeerw.net \
    --cc=roberta.dobrescu@gmail.com \
    --cc=robh+dt@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 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.