From: Jonathan Cameron <jic23@kernel.org>
To: Lars-Peter Clausen <lars@metafoo.de>
Cc: Jonathan Cameron <jic23@cam.ac.uk>,
linux-iio@vger.kernel.org, drivers@analog.com
Subject: Re: [PATCH 2/7] iio:imu:adis: Add support for 32bit registers
Date: Tue, 20 Nov 2012 20:55:34 +0000 [thread overview]
Message-ID: <50ABEE46.7020800@kernel.org> (raw)
In-Reply-To: <1353418611-17614-2-git-send-email-lars@metafoo.de>
On 11/20/2012 01:36 PM, Lars-Peter Clausen wrote:
> Some of the newer generation devices from the ADIS16XXX family have 32bit wide
> register which spans two 16bit wide registers. This patch adds support for
> reading and writing a 32bit wide register.
>
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
added to togreg branch of iio.git
> ---
> drivers/iio/imu/adis.c | 145 +++++++++++++++++++++++++++---------------
> drivers/iio/imu/adis_buffer.c | 2 +
> include/linux/iio/imu/adis.h | 81 +++++++++++++++++++++--
> 3 files changed, 171 insertions(+), 57 deletions(-)
>
> diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c
> index 28d4df2..280a495 100644
> --- a/drivers/iio/imu/adis.c
> +++ b/drivers/iio/imu/adis.c
> @@ -27,36 +27,10 @@
> #define ADIS_MSC_CTRL_DATA_RDY_DIO2 BIT(0)
> #define ADIS_GLOB_CMD_SW_RESET BIT(7)
>
> -/**
> - * adis_write_reg_8() - Write single byte to a register
> - * @adis: The adis device
> - * @reg: The address of the register to be written
> - * @val: The value to write
> - */
> -int adis_write_reg_8(struct adis *adis, unsigned int reg, uint8_t val)
> -{
> - int ret;
> -
> - mutex_lock(&adis->txrx_lock);
> - adis->tx[0] = ADIS_WRITE_REG(reg);
> - adis->tx[1] = val;
> -
> - ret = spi_write(adis->spi, adis->tx, 2);
> - mutex_unlock(&adis->txrx_lock);
> -
> - return ret;
> -}
> -EXPORT_SYMBOL_GPL(adis_write_reg_8);
> -
> -/**
> - * adis_write_reg_16() - Write 2 bytes to a pair of registers
> - * @adis: The adis device
> - * @reg: The address of the lower of the two registers
> - * @val: Value to be written
> - */
> -int adis_write_reg_16(struct adis *adis, unsigned int reg, uint16_t value)
> +int adis_write_reg(struct adis *adis, unsigned int reg,
> + unsigned int value, unsigned int size)
> {
> - int ret;
> + int ret, i;
> struct spi_message msg;
> struct spi_transfer xfers[] = {
> {
> @@ -69,33 +43,69 @@ int adis_write_reg_16(struct adis *adis, unsigned int reg, uint16_t value)
> .tx_buf = adis->tx + 2,
> .bits_per_word = 8,
> .len = 2,
> + .cs_change = 1,
> + .delay_usecs = adis->data->write_delay,
> + }, {
> + .tx_buf = adis->tx + 4,
> + .bits_per_word = 8,
> + .len = 2,
> + .cs_change = 1,
> + .delay_usecs = adis->data->write_delay,
> + }, {
> + .tx_buf = adis->tx + 6,
> + .bits_per_word = 8,
> + .len = 2,
> .delay_usecs = adis->data->write_delay,
> },
> };
>
> mutex_lock(&adis->txrx_lock);
> - adis->tx[0] = ADIS_WRITE_REG(reg);
> - adis->tx[1] = value & 0xff;
> - adis->tx[2] = ADIS_WRITE_REG(reg + 1);
> - adis->tx[3] = (value >> 8) & 0xff;
>
> spi_message_init(&msg);
> - spi_message_add_tail(&xfers[0], &msg);
> - spi_message_add_tail(&xfers[1], &msg);
> + switch (size) {
> + case 4:
> + adis->tx[6] = ADIS_WRITE_REG(reg + 3);
> + adis->tx[7] = (value >> 24) & 0xff;
> + adis->tx[4] = ADIS_WRITE_REG(reg + 2);
> + adis->tx[5] = (value >> 16) & 0xff;
> + case 2:
> + adis->tx[2] = ADIS_WRITE_REG(reg + 1);
> + adis->tx[3] = (value >> 8) & 0xff;
> + case 1:
> + adis->tx[0] = ADIS_WRITE_REG(reg);
> + adis->tx[1] = value & 0xff;
> + break;
> + default:
> + ret = -EINVAL;
> + goto out_unlock;
> + }
> +
> + xfers[size - 1].cs_change = 0;
> +
> + for (i = 0; i < size; i++)
> + spi_message_add_tail(&xfers[i], &msg);
> +
> ret = spi_sync(adis->spi, &msg);
> + if (ret) {
> + dev_err(&adis->spi->dev, "Failed to write register 0x%02X: %d\n",
> + reg, ret);
> + }
> +
> +out_unlock:
> mutex_unlock(&adis->txrx_lock);
>
> return ret;
> }
> -EXPORT_SYMBOL_GPL(adis_write_reg_16);
> +EXPORT_SYMBOL_GPL(adis_write_reg);
>
> /**
> - * adis_read_reg_16() - read 2 bytes from a 16-bit register
> + * adis_read_reg() - read 2 bytes from a 16-bit register
> * @adis: The adis device
> * @reg: The address of the lower of the two registers
> * @val: The value read back from the device
> */
> -int adis_read_reg_16(struct adis *adis, unsigned int reg, uint16_t *val)
> +int adis_read_reg(struct adis *adis, unsigned int reg,
> + unsigned int *val, unsigned int size)
> {
> struct spi_message msg;
> int ret;
> @@ -107,33 +117,61 @@ int adis_read_reg_16(struct adis *adis, unsigned int reg, uint16_t *val)
> .cs_change = 1,
> .delay_usecs = adis->data->read_delay,
> }, {
> + .tx_buf = adis->tx + 2,
> .rx_buf = adis->rx,
> .bits_per_word = 8,
> .len = 2,
> + .cs_change = 1,
> + .delay_usecs = adis->data->read_delay,
> + }, {
> + .rx_buf = adis->rx + 2,
> + .bits_per_word = 8,
> + .len = 2,
> .delay_usecs = adis->data->read_delay,
> },
> };
>
> mutex_lock(&adis->txrx_lock);
> - adis->tx[0] = ADIS_READ_REG(reg);
> - adis->tx[1] = 0;
> -
> spi_message_init(&msg);
> - spi_message_add_tail(&xfers[0], &msg);
> - spi_message_add_tail(&xfers[1], &msg);
> +
> + switch (size) {
> + case 4:
> + adis->tx[0] = ADIS_READ_REG(reg + 2);
> + adis->tx[1] = 0;
> + spi_message_add_tail(&xfers[0], &msg);
> + case 2:
> + adis->tx[2] = ADIS_READ_REG(reg);
> + adis->tx[3] = 0;
> + spi_message_add_tail(&xfers[1], &msg);
> + spi_message_add_tail(&xfers[2], &msg);
> + break;
> + default:
> + ret = -EINVAL;
> + goto out_unlock;
> + }
> +
> ret = spi_sync(adis->spi, &msg);
> if (ret) {
> - dev_err(&adis->spi->dev, "Failed to read 16 bit register 0x%02X: %d\n",
> + dev_err(&adis->spi->dev, "Failed to read register 0x%02X: %d\n",
> reg, ret);
> - goto error_ret;
> + goto out_unlock;
> }
> - *val = get_unaligned_be16(adis->rx);
>
> -error_ret:
> + switch (size) {
> + case 4:
> + *val = get_unaligned_be32(adis->rx);
> + break;
> + case 2:
> + *val = get_unaligned_be16(adis->rx + 2);
> + break;
> + }
> +
> +out_unlock:
> mutex_unlock(&adis->txrx_lock);
> +
> return ret;
> }
> -EXPORT_SYMBOL_GPL(adis_read_reg_16);
> +EXPORT_SYMBOL_GPL(adis_read_reg);
>
> #ifdef CONFIG_DEBUG_FS
>
> @@ -304,25 +342,26 @@ int adis_single_conversion(struct iio_dev *indio_dev,
> const struct iio_chan_spec *chan, unsigned int error_mask, int *val)
> {
> struct adis *adis = iio_device_get_drvdata(indio_dev);
> - uint16_t val16;
> + unsigned int uval;
> int ret;
>
> mutex_lock(&indio_dev->mlock);
>
> - ret = adis_read_reg_16(adis, chan->address, &val16);
> + ret = adis_read_reg(adis, chan->address, &uval,
> + chan->scan_type.storagebits / 8);
> if (ret)
> goto err_unlock;
>
> - if (val16 & error_mask) {
> + if (uval & error_mask) {
> ret = adis_check_status(adis);
> if (ret)
> goto err_unlock;
> }
>
> if (chan->scan_type.sign == 's')
> - *val = sign_extend32(val16, chan->scan_type.realbits - 1);
> + *val = sign_extend32(uval, chan->scan_type.realbits - 1);
> else
> - *val = val16 & ((1 << chan->scan_type.realbits) - 1);
> + *val = uval & ((1 << chan->scan_type.realbits) - 1);
>
> ret = IIO_VAL_INT;
> err_unlock:
> diff --git a/drivers/iio/imu/adis_buffer.c b/drivers/iio/imu/adis_buffer.c
> index a91b4cb..7857133 100644
> --- a/drivers/iio/imu/adis_buffer.c
> +++ b/drivers/iio/imu/adis_buffer.c
> @@ -64,6 +64,8 @@ int adis_update_scan_mode(struct iio_dev *indio_dev,
> for (i = 0; i < indio_dev->num_channels; i++, chan++) {
> if (!test_bit(chan->scan_index, scan_mask))
> continue;
> + if (chan->scan_type.storagebits == 32)
> + *tx++ = cpu_to_be16((chan->address + 2) << 8);
> *tx++ = cpu_to_be16(chan->address << 8);
> }
>
> diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h
> index fce7bc3..6402a08 100644
> --- a/include/linux/iio/imu/adis.h
> +++ b/include/linux/iio/imu/adis.h
> @@ -53,7 +53,7 @@ struct adis {
> struct spi_transfer *xfer;
> void *buffer;
>
> - uint8_t tx[8] ____cacheline_aligned;
> + uint8_t tx[10] ____cacheline_aligned;
> uint8_t rx[4];
> };
>
> @@ -61,9 +61,82 @@ int adis_init(struct adis *adis, struct iio_dev *indio_dev,
> struct spi_device *spi, const struct adis_data *data);
> int adis_reset(struct adis *adis);
>
> -int adis_write_reg_8(struct adis *adis, unsigned int reg, uint8_t val);
> -int adis_write_reg_16(struct adis *adis, unsigned int reg, uint16_t val);
> -int adis_read_reg_16(struct adis *adis, unsigned int reg, uint16_t *val);
> +int adis_write_reg(struct adis *adis, unsigned int reg,
> + unsigned int val, unsigned int size);
> +int adis_read_reg(struct adis *adis, unsigned int reg,
> + unsigned int *val, unsigned int size);
> +
> +/**
> + * adis_write_reg_8() - Write single byte to a register
> + * @adis: The adis device
> + * @reg: The address of the register to be written
> + * @value: The value to write
> + */
> +static inline int adis_write_reg_8(struct adis *adis, unsigned int reg,
> + uint8_t val)
> +{
> + return adis_write_reg(adis, reg, val, 1);
> +}
> +
> +/**
> + * adis_write_reg_16() - Write 2 bytes to a pair of registers
> + * @adis: The adis device
> + * @reg: The address of the lower of the two registers
> + * @value: Value to be written
> + */
> +static inline int adis_write_reg_16(struct adis *adis, unsigned int reg,
> + uint16_t val)
> +{
> + return adis_write_reg(adis, reg, val, 2);
> +}
> +
> +/**
> + * adis_write_reg_32() - write 4 bytes to four registers
> + * @adis: The adis device
> + * @reg: The address of the lower of the four register
> + * @value: Value to be written
> + */
> +static inline int adis_write_reg_32(struct adis *adis, unsigned int reg,
> + uint32_t val)
> +{
> + return adis_write_reg(adis, reg, val, 4);
> +}
> +
> +/**
> + * adis_read_reg_16() - read 2 bytes from a 16-bit register
> + * @adis: The adis device
> + * @reg: The address of the lower of the two registers
> + * @val: The value read back from the device
> + */
> +static inline int adis_read_reg_16(struct adis *adis, unsigned int reg,
> + uint16_t *val)
> +{
> + unsigned int tmp;
> + int ret;
> +
> + ret = adis_read_reg(adis, reg, &tmp, 2);
> + *val = tmp;
> +
> + return ret;
> +}
> +
> +/**
> + * adis_read_reg_32() - read 4 bytes from a 32-bit register
> + * @adis: The adis device
> + * @reg: The address of the lower of the two registers
> + * @val: The value read back from the device
> + */
> +static inline int adis_read_reg_32(struct adis *adis, unsigned int reg,
> + uint32_t *val)
> +{
> + unsigned int tmp;
> + int ret;
> +
> + ret = adis_read_reg(adis, reg, &tmp, 4);
> + *val = tmp;
> +
> + return ret;
> +}
>
> int adis_enable_irq(struct adis *adis, bool enable);
> int adis_check_status(struct adis *adis);
>
next prev parent reply other threads:[~2012-11-20 20:55 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-11-20 13:36 [PATCH 1/7] iio:imu:adis: Add debugfs register access support Lars-Peter Clausen
2012-11-20 13:36 ` [PATCH 2/7] iio:imu:adis: Add support for 32bit registers Lars-Peter Clausen
2012-11-20 20:55 ` Jonathan Cameron [this message]
2012-11-20 13:36 ` [PATCH 3/7] iio:gyro: Add support for the ADIS16136 gyroscope Lars-Peter Clausen
2012-11-20 21:05 ` Jonathan Cameron
2012-11-20 21:15 ` Lars-Peter Clausen
2012-11-20 21:26 ` Jonathan Cameron
2012-11-20 13:36 ` [PATCH 4/7] iio:imu:adis: Add paging support Lars-Peter Clausen
2012-11-20 21:10 ` Jonathan Cameron
2012-11-20 13:36 ` [PATCH 5/7] iio: Add pressure channel type Lars-Peter Clausen
2012-11-20 21:12 ` Jonathan Cameron
2012-11-20 13:36 ` [PATCH 6/7] iio: Factor out fixed point number parsing into its own function Lars-Peter Clausen
2012-11-20 21:14 ` Jonathan Cameron
2012-11-20 13:36 ` [PATCH 7/7] iio:imu: Add support for the ADIS16480 and similar IMUs Lars-Peter Clausen
2012-11-20 21:24 ` Jonathan Cameron
2012-11-20 19:51 ` [PATCH 1/7] iio:imu:adis: Add debugfs register access support 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=50ABEE46.7020800@kernel.org \
--to=jic23@kernel.org \
--cc=drivers@analog.com \
--cc=jic23@cam.ac.uk \
--cc=lars@metafoo.de \
--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 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.