aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2012-11-20 08:36:00 -0500
committerJonathan Cameron <jic23@kernel.org>2012-11-20 14:51:29 -0500
commit57a1228a06b7a5939a8b0078a92b44fa30855bcb (patch)
treeb0cfaf71667f2026fc1d1e7d3ede704731e7d7b6
parent78026a6fde8f7b0ca77c059da11f476d69dfde3b (diff)
iio:imu:adis: Add support for 32bit registers
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> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
-rw-r--r--drivers/iio/imu/adis.c145
-rw-r--r--drivers/iio/imu/adis_buffer.c2
-rw-r--r--include/linux/iio/imu/adis.h81
3 files changed, 171 insertions, 57 deletions
diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c
index 28d4df2fe76a..280a49584adf 100644
--- a/drivers/iio/imu/adis.c
+++ b/drivers/iio/imu/adis.c
@@ -27,36 +27,10 @@
27#define ADIS_MSC_CTRL_DATA_RDY_DIO2 BIT(0) 27#define ADIS_MSC_CTRL_DATA_RDY_DIO2 BIT(0)
28#define ADIS_GLOB_CMD_SW_RESET BIT(7) 28#define ADIS_GLOB_CMD_SW_RESET BIT(7)
29 29
30/** 30int adis_write_reg(struct adis *adis, unsigned int reg,
31 * adis_write_reg_8() - Write single byte to a register 31 unsigned int value, unsigned int size)
32 * @adis: The adis device
33 * @reg: The address of the register to be written
34 * @val: The value to write
35 */
36int adis_write_reg_8(struct adis *adis, unsigned int reg, uint8_t val)
37{
38 int ret;
39
40 mutex_lock(&adis->txrx_lock);
41 adis->tx[0] = ADIS_WRITE_REG(reg);
42 adis->tx[1] = val;
43
44 ret = spi_write(adis->spi, adis->tx, 2);
45 mutex_unlock(&adis->txrx_lock);
46
47 return ret;
48}
49EXPORT_SYMBOL_GPL(adis_write_reg_8);
50
51/**
52 * adis_write_reg_16() - Write 2 bytes to a pair of registers
53 * @adis: The adis device
54 * @reg: The address of the lower of the two registers
55 * @val: Value to be written
56 */
57int adis_write_reg_16(struct adis *adis, unsigned int reg, uint16_t value)
58{ 32{
59 int ret; 33 int ret, i;
60 struct spi_message msg; 34 struct spi_message msg;
61 struct spi_transfer xfers[] = { 35 struct spi_transfer xfers[] = {
62 { 36 {
@@ -69,33 +43,69 @@ int adis_write_reg_16(struct adis *adis, unsigned int reg, uint16_t value)
69 .tx_buf = adis->tx + 2, 43 .tx_buf = adis->tx + 2,
70 .bits_per_word = 8, 44 .bits_per_word = 8,
71 .len = 2, 45 .len = 2,
46 .cs_change = 1,
47 .delay_usecs = adis->data->write_delay,
48 }, {
49 .tx_buf = adis->tx + 4,
50 .bits_per_word = 8,
51 .len = 2,
52 .cs_change = 1,
53 .delay_usecs = adis->data->write_delay,
54 }, {
55 .tx_buf = adis->tx + 6,
56 .bits_per_word = 8,
57 .len = 2,
72 .delay_usecs = adis->data->write_delay, 58 .delay_usecs = adis->data->write_delay,
73 }, 59 },
74 }; 60 };
75 61
76 mutex_lock(&adis->txrx_lock); 62 mutex_lock(&adis->txrx_lock);
77 adis->tx[0] = ADIS_WRITE_REG(reg);
78 adis->tx[1] = value & 0xff;
79 adis->tx[2] = ADIS_WRITE_REG(reg + 1);
80 adis->tx[3] = (value >> 8) & 0xff;
81 63
82 spi_message_init(&msg); 64 spi_message_init(&msg);
83 spi_message_add_tail(&xfers[0], &msg); 65 switch (size) {
84 spi_message_add_tail(&xfers[1], &msg); 66 case 4:
67 adis->tx[6] = ADIS_WRITE_REG(reg + 3);
68 adis->tx[7] = (value >> 24) & 0xff;
69 adis->tx[4] = ADIS_WRITE_REG(reg + 2);
70 adis->tx[5] = (value >> 16) & 0xff;
71 case 2:
72 adis->tx[2] = ADIS_WRITE_REG(reg + 1);
73 adis->tx[3] = (value >> 8) & 0xff;
74 case 1:
75 adis->tx[0] = ADIS_WRITE_REG(reg);
76 adis->tx[1] = value & 0xff;
77 break;
78 default:
79 ret = -EINVAL;
80 goto out_unlock;
81 }
82
83 xfers[size - 1].cs_change = 0;
84
85 for (i = 0; i < size; i++)
86 spi_message_add_tail(&xfers[i], &msg);
87
85 ret = spi_sync(adis->spi, &msg); 88 ret = spi_sync(adis->spi, &msg);
89 if (ret) {
90 dev_err(&adis->spi->dev, "Failed to write register 0x%02X: %d\n",
91 reg, ret);
92 }
93
94out_unlock:
86 mutex_unlock(&adis->txrx_lock); 95 mutex_unlock(&adis->txrx_lock);
87 96
88 return ret; 97 return ret;
89} 98}
90EXPORT_SYMBOL_GPL(adis_write_reg_16); 99EXPORT_SYMBOL_GPL(adis_write_reg);
91 100
92/** 101/**
93 * adis_read_reg_16() - read 2 bytes from a 16-bit register 102 * adis_read_reg() - read 2 bytes from a 16-bit register
94 * @adis: The adis device 103 * @adis: The adis device
95 * @reg: The address of the lower of the two registers 104 * @reg: The address of the lower of the two registers
96 * @val: The value read back from the device 105 * @val: The value read back from the device
97 */ 106 */
98int adis_read_reg_16(struct adis *adis, unsigned int reg, uint16_t *val) 107int adis_read_reg(struct adis *adis, unsigned int reg,
108 unsigned int *val, unsigned int size)
99{ 109{
100 struct spi_message msg; 110 struct spi_message msg;
101 int ret; 111 int ret;
@@ -107,33 +117,61 @@ int adis_read_reg_16(struct adis *adis, unsigned int reg, uint16_t *val)
107 .cs_change = 1, 117 .cs_change = 1,
108 .delay_usecs = adis->data->read_delay, 118 .delay_usecs = adis->data->read_delay,
109 }, { 119 }, {
120 .tx_buf = adis->tx + 2,
110 .rx_buf = adis->rx, 121 .rx_buf = adis->rx,
111 .bits_per_word = 8, 122 .bits_per_word = 8,
112 .len = 2, 123 .len = 2,
124 .cs_change = 1,
125 .delay_usecs = adis->data->read_delay,
126 }, {
127 .rx_buf = adis->rx + 2,
128 .bits_per_word = 8,
129 .len = 2,
113 .delay_usecs = adis->data->read_delay, 130 .delay_usecs = adis->data->read_delay,
114 }, 131 },
115 }; 132 };
116 133
117 mutex_lock(&adis->txrx_lock); 134 mutex_lock(&adis->txrx_lock);
118 adis->tx[0] = ADIS_READ_REG(reg);
119 adis->tx[1] = 0;
120
121 spi_message_init(&msg); 135 spi_message_init(&msg);
122 spi_message_add_tail(&xfers[0], &msg); 136
123 spi_message_add_tail(&xfers[1], &msg); 137 switch (size) {
138 case 4:
139 adis->tx[0] = ADIS_READ_REG(reg + 2);
140 adis->tx[1] = 0;
141 spi_message_add_tail(&xfers[0], &msg);
142 case 2:
143 adis->tx[2] = ADIS_READ_REG(reg);
144 adis->tx[3] = 0;
145 spi_message_add_tail(&xfers[1], &msg);
146 spi_message_add_tail(&xfers[2], &msg);
147 break;
148 default:
149 ret = -EINVAL;
150 goto out_unlock;
151 }
152
124 ret = spi_sync(adis->spi, &msg); 153 ret = spi_sync(adis->spi, &msg);
125 if (ret) { 154 if (ret) {
126 dev_err(&adis->spi->dev, "Failed to read 16 bit register 0x%02X: %d\n", 155 dev_err(&adis->spi->dev, "Failed to read register 0x%02X: %d\n",
127 reg, ret); 156 reg, ret);
128 goto error_ret; 157 goto out_unlock;
129 } 158 }
130 *val = get_unaligned_be16(adis->rx);
131 159
132error_ret: 160 switch (size) {
161 case 4:
162 *val = get_unaligned_be32(adis->rx);
163 break;
164 case 2:
165 *val = get_unaligned_be16(adis->rx + 2);
166 break;
167 }
168
169out_unlock:
133 mutex_unlock(&adis->txrx_lock); 170 mutex_unlock(&adis->txrx_lock);
171
134 return ret; 172 return ret;
135} 173}
136EXPORT_SYMBOL_GPL(adis_read_reg_16); 174EXPORT_SYMBOL_GPL(adis_read_reg);
137 175
138#ifdef CONFIG_DEBUG_FS 176#ifdef CONFIG_DEBUG_FS
139 177
@@ -304,25 +342,26 @@ int adis_single_conversion(struct iio_dev *indio_dev,
304 const struct iio_chan_spec *chan, unsigned int error_mask, int *val) 342 const struct iio_chan_spec *chan, unsigned int error_mask, int *val)
305{ 343{
306 struct adis *adis = iio_device_get_drvdata(indio_dev); 344 struct adis *adis = iio_device_get_drvdata(indio_dev);
307 uint16_t val16; 345 unsigned int uval;
308 int ret; 346 int ret;
309 347
310 mutex_lock(&indio_dev->mlock); 348 mutex_lock(&indio_dev->mlock);
311 349
312 ret = adis_read_reg_16(adis, chan->address, &val16); 350 ret = adis_read_reg(adis, chan->address, &uval,
351 chan->scan_type.storagebits / 8);
313 if (ret) 352 if (ret)
314 goto err_unlock; 353 goto err_unlock;
315 354
316 if (val16 & error_mask) { 355 if (uval & error_mask) {
317 ret = adis_check_status(adis); 356 ret = adis_check_status(adis);
318 if (ret) 357 if (ret)
319 goto err_unlock; 358 goto err_unlock;
320 } 359 }
321 360
322 if (chan->scan_type.sign == 's') 361 if (chan->scan_type.sign == 's')
323 *val = sign_extend32(val16, chan->scan_type.realbits - 1); 362 *val = sign_extend32(uval, chan->scan_type.realbits - 1);
324 else 363 else
325 *val = val16 & ((1 << chan->scan_type.realbits) - 1); 364 *val = uval & ((1 << chan->scan_type.realbits) - 1);
326 365
327 ret = IIO_VAL_INT; 366 ret = IIO_VAL_INT;
328err_unlock: 367err_unlock:
diff --git a/drivers/iio/imu/adis_buffer.c b/drivers/iio/imu/adis_buffer.c
index a91b4cbdc73a..785713349e9f 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,
64 for (i = 0; i < indio_dev->num_channels; i++, chan++) { 64 for (i = 0; i < indio_dev->num_channels; i++, chan++) {
65 if (!test_bit(chan->scan_index, scan_mask)) 65 if (!test_bit(chan->scan_index, scan_mask))
66 continue; 66 continue;
67 if (chan->scan_type.storagebits == 32)
68 *tx++ = cpu_to_be16((chan->address + 2) << 8);
67 *tx++ = cpu_to_be16(chan->address << 8); 69 *tx++ = cpu_to_be16(chan->address << 8);
68 } 70 }
69 71
diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h
index fce7bc3ba0b5..6402a08c0e65 100644
--- a/include/linux/iio/imu/adis.h
+++ b/include/linux/iio/imu/adis.h
@@ -53,7 +53,7 @@ struct adis {
53 struct spi_transfer *xfer; 53 struct spi_transfer *xfer;
54 void *buffer; 54 void *buffer;
55 55
56 uint8_t tx[8] ____cacheline_aligned; 56 uint8_t tx[10] ____cacheline_aligned;
57 uint8_t rx[4]; 57 uint8_t rx[4];
58}; 58};
59 59
@@ -61,9 +61,82 @@ int adis_init(struct adis *adis, struct iio_dev *indio_dev,
61 struct spi_device *spi, const struct adis_data *data); 61 struct spi_device *spi, const struct adis_data *data);
62int adis_reset(struct adis *adis); 62int adis_reset(struct adis *adis);
63 63
64int adis_write_reg_8(struct adis *adis, unsigned int reg, uint8_t val); 64int adis_write_reg(struct adis *adis, unsigned int reg,
65int adis_write_reg_16(struct adis *adis, unsigned int reg, uint16_t val); 65 unsigned int val, unsigned int size);
66int adis_read_reg_16(struct adis *adis, unsigned int reg, uint16_t *val); 66int adis_read_reg(struct adis *adis, unsigned int reg,
67 unsigned int *val, unsigned int size);
68
69/**
70 * adis_write_reg_8() - Write single byte to a register
71 * @adis: The adis device
72 * @reg: The address of the register to be written
73 * @value: The value to write
74 */
75static inline int adis_write_reg_8(struct adis *adis, unsigned int reg,
76 uint8_t val)
77{
78 return adis_write_reg(adis, reg, val, 1);
79}
80
81/**
82 * adis_write_reg_16() - Write 2 bytes to a pair of registers
83 * @adis: The adis device
84 * @reg: The address of the lower of the two registers
85 * @value: Value to be written
86 */
87static inline int adis_write_reg_16(struct adis *adis, unsigned int reg,
88 uint16_t val)
89{
90 return adis_write_reg(adis, reg, val, 2);
91}
92
93/**
94 * adis_write_reg_32() - write 4 bytes to four registers
95 * @adis: The adis device
96 * @reg: The address of the lower of the four register
97 * @value: Value to be written
98 */
99static inline int adis_write_reg_32(struct adis *adis, unsigned int reg,
100 uint32_t val)
101{
102 return adis_write_reg(adis, reg, val, 4);
103}
104
105/**
106 * adis_read_reg_16() - read 2 bytes from a 16-bit register
107 * @adis: The adis device
108 * @reg: The address of the lower of the two registers
109 * @val: The value read back from the device
110 */
111static inline int adis_read_reg_16(struct adis *adis, unsigned int reg,
112 uint16_t *val)
113{
114 unsigned int tmp;
115 int ret;
116
117 ret = adis_read_reg(adis, reg, &tmp, 2);
118 *val = tmp;
119
120 return ret;
121}
122
123/**
124 * adis_read_reg_32() - read 4 bytes from a 32-bit register
125 * @adis: The adis device
126 * @reg: The address of the lower of the two registers
127 * @val: The value read back from the device
128 */
129static inline int adis_read_reg_32(struct adis *adis, unsigned int reg,
130 uint32_t *val)
131{
132 unsigned int tmp;
133 int ret;
134
135 ret = adis_read_reg(adis, reg, &tmp, 4);
136 *val = tmp;
137
138 return ret;
139}
67 140
68int adis_enable_irq(struct adis *adis, bool enable); 141int adis_enable_irq(struct adis *adis, bool enable);
69int adis_check_status(struct adis *adis); 142int adis_check_status(struct adis *adis);