Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 338012
b: refs/heads/master
c: 57a1228
h: refs/heads/master
v: v3
  • Loading branch information
Lars-Peter Clausen authored and Jonathan Cameron committed Nov 20, 2012
1 parent 167ca89 commit 33c1eb5
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 58 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 78026a6fde8f7b0ca77c059da11f476d69dfde3b
refs/heads/master: 57a1228a06b7a5939a8b0078a92b44fa30855bcb
145 changes: 92 additions & 53 deletions trunk/drivers/iio/imu/adis.c
Original file line number Diff line number Diff line change
Expand Up @@ -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[] = {
{
Expand All @@ -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;
Expand All @@ -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

Expand Down Expand Up @@ -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:
Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/iio/imu/adis_buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
81 changes: 77 additions & 4 deletions trunk/include/linux/iio/imu/adis.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,90 @@ struct adis {
struct spi_transfer *xfer;
void *buffer;

uint8_t tx[8] ____cacheline_aligned;
uint8_t tx[10] ____cacheline_aligned;
uint8_t rx[4];
};

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);
Expand Down

0 comments on commit 33c1eb5

Please sign in to comment.